-
Notifications
You must be signed in to change notification settings - Fork 222
Allow multiple bridges for token #387
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,17 +8,29 @@ import "./interfaces/IBurnableMintableERC677Token.sol"; | |
| import "./upgradeable_contracts/Claimable.sol"; | ||
|
|
||
| contract ERC677BridgeToken is IBurnableMintableERC677Token, DetailedERC20, BurnableToken, MintableToken, Claimable { | ||
| address public bridgeContract; | ||
| address[] internal _bridgeContracts; | ||
| mapping(address => bool) internal _isBridgeContract; | ||
|
|
||
| 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 | ||
| } | ||
|
|
||
| function setBridgeContract(address _bridgeContract) external onlyOwner { | ||
| require(AddressUtils.isContract(_bridgeContract)); | ||
| bridgeContract = _bridgeContract; | ||
| function setBridgeContracts(address[] _contracts) external onlyOwner { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we consider a case when the bridge is required to be removed from the list. E.g. we shut down it by some reasons?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The new For example, we have three bridges:
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok. Got you. Does it look like that we need to delete element here in order to get gas refund? Imagine that we are completely overwriting the array and replacing
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you mean using |
||
| require(_contracts.length > 0); | ||
| uint256 i; | ||
|
|
||
| for (i = 0; i < _bridgeContracts.length; i++) { | ||
| _isBridgeContract[_bridgeContracts[i]] = false; | ||
| } | ||
|
|
||
| _bridgeContracts = _contracts; | ||
|
|
||
| for (i = 0; i < _contracts.length; i++) { | ||
| require(AddressUtils.isContract(_contracts[i])); | ||
| _isBridgeContract[_contracts[i]] = true; | ||
| } | ||
| } | ||
|
|
||
| modifier validRecipient(address _recipient) { | ||
|
|
@@ -27,6 +39,10 @@ contract ERC677BridgeToken is IBurnableMintableERC677Token, DetailedERC20, Burna | |
| _; | ||
| } | ||
|
|
||
| function bridgeContracts() external view returns (address[]) { | ||
| return _bridgeContracts; | ||
| } | ||
|
|
||
| function transferAndCall(address _to, uint256 _value, bytes _data) external validRecipient(_to) returns (bool) { | ||
| require(superTransfer(_to, _value)); | ||
| emit Transfer(msg.sender, _to, _value, _data); | ||
|
|
@@ -59,7 +75,7 @@ contract ERC677BridgeToken is IBurnableMintableERC677Token, DetailedERC20, Burna | |
|
|
||
| function callAfterTransfer(address _from, address _to, uint256 _value) internal { | ||
| if (AddressUtils.isContract(_to) && !contractFallback(_from, _to, _value, new bytes(0))) { | ||
| require(_to != bridgeContract); | ||
| require(!_isBridgeContract[_to]); | ||
| emit ContractFallbackCallFailed(_from, _to, _value); | ||
| } | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
well... we can reduce gas consumption if the approach similar to storing the bridge validators will be applied.
It will allow to use the same structure to keep both the list of bridges and quick access to check the allowance to use them.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although I don't expect to have a lot of bridges, I agree with you that it should use the linked-list approach. But since there is
MAX_VALIDATORSlimit of50items (because of block gas limit, I guess) and_removeValidatorrequires looping through the list, I'm not sure this approach would significantly win in gas. However, it could win in storage space (because the list approach uses one uint256 field and one mapping against my approach which uses an array and a mapping), but in case of a small number of bridges it doesn't matter.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, I assume that
setBridgeContractsis a rare operation.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In fact, any array in Solidity requires N+1 storage slots: N storage for the N array elements and 1 element to store the array index/length. So, storing the one bridge address in the linked list has the same efficiency as your approach, storing two bridge addresses in the linked list will consume less gas (by 1 storage slot), storing 3 bridge addresses -- by 2 storage slots etc. Here we are not considering the case that a transaction to send an array with one element requires more bytes since the array is RLP-encoded, so, even to decode the input data EVM will spend more resources.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BTW,
50is a limitation which was asked to be added on one of the previous security audit. Bearing in the mind the same idea, it makes sense to limit the size of the bridge addresses list.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I will change the code making it similar to the linked-list approach you are proposing.