import { BigNumber , BigNumberish , constants , Wallet } from 'ethers' ; import { solidity } from 'ethereum-waffle' ; import { expect , use } from 'chai' ; import { initialSupply , setupTrueGold } from 'fixtures/trueGold' ; import { toAddress , WalletOrAddress } from 'utils' ; import { loadFixture } from 'fixtures/beforeEachWithFixture' ; import { TrueGold } from 'contracts' ; use ( solidity ) ; describe ( 'TrueGold - ERC20Burnable' , ( ) => { let initialHolder ; let secondAccount ; let token ; function approve ( tokenOwner , spender , amount ) { const asTokenOwner = token . connect ( tokenOwner ) ; return asTokenOwner . approve ( toAddress ( spender ) , amount ) ; } beforeEach ( async ( ) => { ( { initialHolder , secondAccount , token } = await loadFixture ( setupTrueGold ) ) ; } ) ; describe ( 'burn' , ( ) => { function burn ( caller , amount ) { return token . connect ( caller ) . burn ( amount ) ; } describe ( 'when the given amount is not greater than balance of the sender' , ( ) => { describe ( 'for a zero amount' , ( ) => { shouldBurn ( 0 ) ; } ) ; describe ( 'for a non-zero amount' , ( ) => { shouldBurn ( 12441000 ) ; } ) ; function shouldBurn ( amount ) { it ( 'burns the requested amount' , async ( ) => { await burn ( initialHolder , amount ) ; expect ( await token . balanceOf ( initialHolder . address ) ) . to . eq ( initialSupply . sub ( amount ) ) ; expect ( await token . totalSupply ( ) ) . to . eq ( initialSupply . sub ( amount ) ) ; } ) ; it ( 'emits a transfer event' , async ( ) => { await expect ( burn ( initialHolder , amount ) ) . to . emit ( token , 'Transfer' ) . withArgs ( initialHolder . address , constants . AddressZero , amount ) ; } ) ; } } ) ; describe ( 'when the given amount is greater than the balance of the sender' , ( ) => { it ( 'reverts' , async ( ) => { await expect ( burn ( initialHolder , initialSupply . add ( 12441000 ) ) ) . to . be . revertedWith ( 'ERC20: burn amount exceeds balance' ) ; } ) ; } ) ; } ) ; describe ( 'burnFrom' , ( ) => { function burnFrom ( caller , tokenOwner , amount ) { return token . connect ( caller ) . burnFrom ( tokenOwner . address , amount ) ; } const initialBalance = initialSupply ; let tokenOwner ; let burner ; beforeEach ( ( ) => { tokenOwner = initialHolder ; burner = secondAccount ; } ) ; describe ( 'on success' , ( ) => { describe ( 'for a zero amount' , ( ) => { shouldBurnFrom ( BigNumber . from ( 0 ) ) ; } ) ; describe ( 'for a non-zero amount' , ( ) => { shouldBurnFrom ( BigNumber . from ( 12441000 ) ) ; } ) ; function shouldBurnFrom ( amount ) { const originalAllowance = amount . mul ( 3 ) ; beforeEach ( async ( ) => { await approve ( tokenOwner , burner , originalAllowance ) ; } ) ; it ( 'burns the requested amount' , async ( ) => { await burnFrom ( burner , tokenOwner , amount ) ; expect ( await token . balanceOf ( tokenOwner . address ) ) . to . eq ( initialBalance . sub ( amount ) ) ; expect ( await token . totalSupply ( ) ) . to . eq ( initialSupply . sub ( amount ) ) ; } ) ; it ( 'decrements allowance' , async ( ) => { await burnFrom ( burner , tokenOwner , amount ) ; expect ( await token . allowance ( tokenOwner . address , burner . address ) ) . to . eq ( originalAllowance . sub ( amount ) ) ; } ) ; it ( 'emits a transfer event' , async ( ) => { await expect ( burnFrom ( burner , tokenOwner , amount ) ) . to . emit ( token , 'Transfer' ) . withArgs ( tokenOwner . address , constants . AddressZero , amount ) ; } ) ; } } ) ; describe ( 'when the given amount is greater than the balance of the sender' , ( ) => { const amount = initialBalance . add ( 12441000 ) ; it ( 'reverts' , async ( ) => { await approve ( tokenOwner , burner , amount ) ; await expect ( burnFrom ( burner , tokenOwner , amount ) ) . to . be . revertedWith ( 'ERC20: burn amount exceeds balance' ) ; } ) ; } ) ; describe ( 'when the given amount is greater than the allowance' , ( ) => { const allowance = BigNumber . from ( 12441000 ) ; it ( 'reverts' , async ( ) => { await approve ( tokenOwner , burner , allowance ) ; await expect ( burnFrom ( burner , tokenOwner , allowance . mul ( 2 ) ) ) . to . be . revertedWith ( 'ERC20Burnable: burn amount exceeds allowance' ) ; } ) ; } ) ; } ) ; } ) ;