Update ERC677 to call onTokenTransfer only for the bridge contract (#530)
This commit is contained in:
parent
d94ad55f52
commit
f70426c841
|
@ -16,8 +16,6 @@ contract ERC677BridgeToken is IBurnableMintableERC677Token, DetailedERC20, Burna
|
|||
|
||||
address internal bridgeContractAddr;
|
||||
|
||||
event ContractFallbackCallFailed(address from, address to, uint256 value);
|
||||
|
||||
constructor(string _name, string _symbol, uint8 _decimals) public DetailedERC20(_name, _symbol, _decimals) {
|
||||
// solhint-disable-previous-line no-empty-blocks
|
||||
}
|
||||
|
@ -67,10 +65,17 @@ contract ERC677BridgeToken is IBurnableMintableERC677Token, DetailedERC20, Burna
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Internal function that calls onTokenTransfer callback on the receiver after the successful transfer.
|
||||
* Since it is not present in the original ERC677 standard, the callback is only called on the bridge contract,
|
||||
* in order to simplify UX. In other cases, this token complies with the ERC677/ERC20 standard.
|
||||
* @param _from tokens sender address.
|
||||
* @param _to tokens receiver address.
|
||||
* @param _value amount of sent tokens.
|
||||
*/
|
||||
function callAfterTransfer(address _from, address _to, uint256 _value) internal {
|
||||
if (AddressUtils.isContract(_to) && !contractFallback(_from, _to, _value, new bytes(0))) {
|
||||
require(!isBridge(_to));
|
||||
emit ContractFallbackCallFailed(_from, _to, _value);
|
||||
if (isBridge(_to)) {
|
||||
require(contractFallback(_from, _to, _value, new bytes(0)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,6 @@ contract('ForeignAMBErc20ToNative', async accounts => {
|
|||
await ambBridgeContract.setMaxGasPerTx(maxGasPerTx)
|
||||
otherSideMediator = await HomeAMBErc20ToNative.new()
|
||||
token = await ERC677BridgeToken.new('TEST', 'TST', 18)
|
||||
await token.setBridgeContract(contract.address)
|
||||
})
|
||||
|
||||
describe('initialize', () => {
|
||||
|
@ -373,8 +372,8 @@ contract('ForeignAMBErc20ToNative', async accounts => {
|
|||
|
||||
describe('handleBridgedTokens', () => {
|
||||
it('should unlock tokens on message from amb', async () => {
|
||||
await token.transfer(contract.address, value, { from: user }).should.be.fulfilled
|
||||
await token.transfer(contract.address, value, { from: user }).should.be.fulfilled
|
||||
await token.transferAndCall(contract.address, value, '0x', { from: user }).should.be.fulfilled
|
||||
await token.transferAndCall(contract.address, value, '0x', { from: user }).should.be.fulfilled
|
||||
expect(await token.balanceOf(contract.address)).to.be.bignumber.equal(twoEthers)
|
||||
expect(await contract.mediatorBalance()).to.be.bignumber.equal(twoEthers)
|
||||
|
||||
|
@ -429,8 +428,8 @@ contract('ForeignAMBErc20ToNative', async accounts => {
|
|||
owner,
|
||||
token.address
|
||||
).should.be.fulfilled
|
||||
await token.transfer(contract.address, value, { from: user }).should.be.fulfilled
|
||||
await token.transfer(contract.address, value, { from: user }).should.be.fulfilled
|
||||
await token.transferAndCall(contract.address, value, '0x', { from: user }).should.be.fulfilled
|
||||
await token.transferAndCall(contract.address, value, '0x', { from: user }).should.be.fulfilled
|
||||
expect(await token.balanceOf(contract.address)).to.be.bignumber.equal(twoEthers)
|
||||
expect(await contract.mediatorBalance()).to.be.bignumber.equal(twoEthers)
|
||||
|
||||
|
@ -462,8 +461,8 @@ contract('ForeignAMBErc20ToNative', async accounts => {
|
|||
})
|
||||
|
||||
it('should revert when out of execution limits on message from amb', async () => {
|
||||
await token.transfer(contract.address, value, { from: user }).should.be.fulfilled
|
||||
await token.transfer(contract.address, value, { from: user }).should.be.fulfilled
|
||||
await token.transferAndCall(contract.address, value, '0x', { from: user }).should.be.fulfilled
|
||||
await token.transferAndCall(contract.address, value, '0x', { from: user }).should.be.fulfilled
|
||||
expect(await token.balanceOf(contract.address)).to.be.bignumber.equal(twoEthers)
|
||||
expect(await contract.mediatorBalance()).to.be.bignumber.equal(twoEthers)
|
||||
|
||||
|
@ -515,7 +514,7 @@ contract('ForeignAMBErc20ToNative', async accounts => {
|
|||
})
|
||||
|
||||
it('should be a failed transaction', async () => {
|
||||
await token.transfer(contract.address, value, { from: user }).should.be.fulfilled
|
||||
await token.transferAndCall(contract.address, value, '0x', { from: user }).should.be.fulfilled
|
||||
// Given
|
||||
const data = await contract.contract.methods.handleBridgedTokens(user, value.toString()).encodeABI()
|
||||
|
||||
|
|
|
@ -44,10 +44,6 @@ contract('ForeignMultiAMBErc20ToErc677', async accounts => {
|
|||
})
|
||||
|
||||
const sendFunctions = [
|
||||
async function simpleTransfer() {
|
||||
await token.transfer(contract.address, value, { from: user }).should.be.fulfilled
|
||||
return user
|
||||
},
|
||||
async function emptyAlternativeReceiver() {
|
||||
await token.transferAndCall(contract.address, value, '0x', { from: user }).should.be.fulfilled
|
||||
return user
|
||||
|
@ -221,7 +217,7 @@ contract('ForeignMultiAMBErc20ToErc677', async accounts => {
|
|||
await token.mint(user, oneEther).should.be.fulfilled
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal(oneEther)
|
||||
|
||||
await token.transfer(contract.address, oneEther, { from: user }).should.be.fulfilled
|
||||
await token.transferAndCall(contract.address, oneEther, '0x', { from: user }).should.be.fulfilled
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal(ZERO)
|
||||
expect(await token.balanceOf(contract.address)).to.be.bignumber.equal(oneEther)
|
||||
|
||||
|
@ -329,7 +325,7 @@ contract('ForeignMultiAMBErc20ToErc677', async accounts => {
|
|||
await contract.setExecutionDailyLimit(token.address, ether('5'), { from: owner }).should.be.rejected
|
||||
await contract.setExecutionMaxPerTx(token.address, ether('1.5'), { from: owner }).should.be.rejected
|
||||
|
||||
await token.transfer(contract.address, value, { from: user })
|
||||
await token.transferAndCall(contract.address, value, '0x', { from: user })
|
||||
|
||||
await contract.setDailyLimit(token.address, ether('5'), { from: owner }).should.be.fulfilled
|
||||
await contract.setMaxPerTx(token.address, ether('1.5'), { from: owner }).should.be.fulfilled
|
||||
|
@ -513,7 +509,7 @@ contract('ForeignMultiAMBErc20ToErc677', async accounts => {
|
|||
|
||||
token = await ERC677BridgeToken.new('TEST', 'TST', decimals)
|
||||
await token.mint(user, value.mul(f1).div(f2)).should.be.fulfilled
|
||||
await token.transfer(contract.address, value.mul(f1).div(f2), { from: user }).should.be.fulfilled
|
||||
await token.transferAndCall(contract.address, value.mul(f1).div(f2), '0x', { from: user }).should.be.fulfilled
|
||||
|
||||
expect(await contract.dailyLimit(token.address)).to.be.bignumber.equal(dailyLimit.mul(f1).div(f2))
|
||||
expect(await contract.maxPerTx(token.address)).to.be.bignumber.equal(maxPerTx.mul(f1).div(f2))
|
||||
|
@ -530,7 +526,7 @@ contract('ForeignMultiAMBErc20ToErc677', async accounts => {
|
|||
it(`should initialize limits according to decimals = 0`, async () => {
|
||||
token = await ERC677BridgeToken.new('TEST', 'TST', 0)
|
||||
await token.mint(user, '1').should.be.fulfilled
|
||||
await token.transfer(contract.address, '1', { from: user }).should.be.fulfilled
|
||||
await token.transferAndCall(contract.address, '1', '0x', { from: user }).should.be.fulfilled
|
||||
|
||||
expect(await contract.dailyLimit(token.address)).to.be.bignumber.equal('10000')
|
||||
expect(await contract.maxPerTx(token.address)).to.be.bignumber.equal('100')
|
||||
|
@ -542,8 +538,8 @@ contract('ForeignMultiAMBErc20ToErc677', async accounts => {
|
|||
|
||||
describe('handleBridgedTokens', () => {
|
||||
it('should unlock tokens on message from amb', async () => {
|
||||
await token.transfer(contract.address, value, { from: user }).should.be.fulfilled
|
||||
await token.transfer(contract.address, value, { from: user }).should.be.fulfilled
|
||||
await token.transferAndCall(contract.address, value, '0x', { from: user }).should.be.fulfilled
|
||||
await token.transferAndCall(contract.address, value, '0x', { from: user }).should.be.fulfilled
|
||||
expect(await token.balanceOf(contract.address)).to.be.bignumber.equal(twoEthers)
|
||||
expect(await contract.mediatorBalance(token.address)).to.be.bignumber.equal(twoEthers)
|
||||
|
||||
|
@ -605,8 +601,8 @@ contract('ForeignMultiAMBErc20ToErc677', async accounts => {
|
|||
})
|
||||
|
||||
it('should not allow to operate when global shutdown is enabled', async () => {
|
||||
await token.transfer(contract.address, value, { from: user }).should.be.fulfilled
|
||||
await token.transfer(contract.address, value, { from: user }).should.be.fulfilled
|
||||
await token.transferAndCall(contract.address, value, '0x', { from: user }).should.be.fulfilled
|
||||
await token.transferAndCall(contract.address, value, '0x', { from: user }).should.be.fulfilled
|
||||
|
||||
const data = await contract.contract.methods
|
||||
.handleBridgedTokens(token.address, user, value.toString())
|
||||
|
@ -662,7 +658,7 @@ contract('ForeignMultiAMBErc20ToErc677', async accounts => {
|
|||
})
|
||||
|
||||
it('should be a failed transaction', async () => {
|
||||
await token.transfer(contract.address, value, { from: user }).should.be.fulfilled
|
||||
await token.transferAndCall(contract.address, value, '0x', { from: user }).should.be.fulfilled
|
||||
// Given
|
||||
const data = await contract.contract.methods
|
||||
.handleBridgedTokens(token.address, user, value.toString())
|
||||
|
@ -857,7 +853,7 @@ contract('ForeignMultiAMBErc20ToErc677', async accounts => {
|
|||
expect(await contract.mediatorBalance(token.address)).to.be.bignumber.equal(ZERO)
|
||||
expect(await token.balanceOf(contract.address)).to.be.bignumber.equal(twoEthers)
|
||||
|
||||
await token.transfer(contract.address, halfEther, { from: user }).should.be.fulfilled
|
||||
await token.transferAndCall(contract.address, halfEther, '0x', { from: user }).should.be.fulfilled
|
||||
await contract.setDailyLimit(token.address, ether('5')).should.be.fulfilled
|
||||
await contract.setMaxPerTx(token.address, ether('2')).should.be.fulfilled
|
||||
|
||||
|
@ -884,7 +880,7 @@ contract('ForeignMultiAMBErc20ToErc677', async accounts => {
|
|||
expect(await contract.mediatorBalance(token.address)).to.be.bignumber.equal(ZERO)
|
||||
expect(await token.balanceOf(contract.address)).to.be.bignumber.equal(twoEthers)
|
||||
|
||||
await token.transfer(contract.address, halfEther, { from: user }).should.be.fulfilled
|
||||
await token.transferAndCall(contract.address, halfEther, '0x', { from: user }).should.be.fulfilled
|
||||
|
||||
expect(await contract.mediatorBalance(token.address)).to.be.bignumber.equal(halfEther)
|
||||
expect(await token.balanceOf(contract.address)).to.be.bignumber.equal(twoEthers.add(halfEther))
|
||||
|
|
|
@ -97,7 +97,8 @@ contract('HomeMultiAMBErc20ToErc677', async accounts => {
|
|||
|
||||
async function bridgeToken(token, value = oneEther, forceFail = false) {
|
||||
await token.mint(user, value).should.be.fulfilled
|
||||
const { receipt } = await token.transfer(otherSideMediator.address, value, { from: user }).should.be.fulfilled
|
||||
const { receipt } = await token.transferAndCall(otherSideMediator.address, value, '0x', { from: user }).should.be
|
||||
.fulfilled
|
||||
const encodedData = strip0x(
|
||||
web3.eth.abi.decodeParameters(
|
||||
['bytes'],
|
||||
|
|
|
@ -309,23 +309,6 @@ function testERC677BridgeToken(accounts, rewardable, permittable, createToken) {
|
|||
})
|
||||
})
|
||||
|
||||
it('sends tokens to contract that does not contains onTokenTransfer method', async () => {
|
||||
await addBridge(token, homeErcToErcContract.address).should.be.fulfilled
|
||||
await token.mint(user, oneEther, { from: owner }).should.be.fulfilled
|
||||
|
||||
const result = await token.transfer(validatorContract.address, minPerTx, { from: user }).should.be.fulfilled
|
||||
expectEventInLogs(result.logs, 'Transfer', {
|
||||
from: user,
|
||||
to: validatorContract.address,
|
||||
value: minPerTx
|
||||
})
|
||||
expectEventInLogs(result.logs, 'ContractFallbackCallFailed', {
|
||||
from: user,
|
||||
to: validatorContract.address,
|
||||
value: minPerTx
|
||||
})
|
||||
})
|
||||
|
||||
it('fail to send tokens to bridge contract out of limits', async () => {
|
||||
const lessThanMin = ether('0.0001')
|
||||
await token.mint(user, oneEther, { from: owner }).should.be.fulfilled
|
||||
|
@ -588,7 +571,7 @@ function testERC677BridgeToken(accounts, rewardable, permittable, createToken) {
|
|||
})
|
||||
})
|
||||
describe('#transfer', async () => {
|
||||
it('if transfer called on contract, onTokenTransfer is also invoked', async () => {
|
||||
it('if transfer called on contract, onTokenTransfer is not invoked', async () => {
|
||||
const receiver = await ERC677ReceiverTest.new()
|
||||
expect(await receiver.from()).to.be.equal(ZERO_ADDRESS)
|
||||
expect(await receiver.value()).to.be.bignumber.equal(ZERO)
|
||||
|
@ -600,8 +583,8 @@ function testERC677BridgeToken(accounts, rewardable, permittable, createToken) {
|
|||
|
||||
expect(await token.balanceOf(receiver.address)).to.be.bignumber.equal('1')
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal(ZERO)
|
||||
expect(await receiver.from()).to.be.equal(user)
|
||||
expect(await receiver.value()).to.be.bignumber.equal('1')
|
||||
expect(await receiver.from()).to.be.equal(ZERO_ADDRESS)
|
||||
expect(await receiver.value()).to.be.bignumber.equal(ZERO)
|
||||
expect(await receiver.data()).to.be.equal(null)
|
||||
expect(logs[0].event).to.be.equal('Transfer')
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue