From ddbed89b3a994d697e84b3d3467428b467edb1f7 Mon Sep 17 00:00:00 2001 From: dapplion <35266934+dapplion@users.noreply.github.com> Date: Wed, 3 Apr 2024 15:40:00 +0900 Subject: [PATCH 1/2] Copy ERC677BridgeToken --- contracts/ERC677BridgeFixedSupplyToken.sol | 122 +++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 contracts/ERC677BridgeFixedSupplyToken.sol diff --git a/contracts/ERC677BridgeFixedSupplyToken.sol b/contracts/ERC677BridgeFixedSupplyToken.sol new file mode 100644 index 000000000..ba49255fe --- /dev/null +++ b/contracts/ERC677BridgeFixedSupplyToken.sol @@ -0,0 +1,122 @@ +pragma solidity 0.4.24; + +import "openzeppelin-solidity/contracts/token/ERC20/BurnableToken.sol"; +import "openzeppelin-solidity/contracts/token/ERC20/MintableToken.sol"; +import "openzeppelin-solidity/contracts/token/ERC20/DetailedERC20.sol"; +import "openzeppelin-solidity/contracts/AddressUtils.sol"; +import "./interfaces/IBurnableMintableERC677Token.sol"; +import "./upgradeable_contracts/Claimable.sol"; + +/** +* @title ERC677BridgeToken +* @dev The basic implementation of a bridgeable ERC677-compatible token +*/ +contract ERC677BridgeToken is IBurnableMintableERC677Token, DetailedERC20, BurnableToken, MintableToken, Claimable { + bytes4 internal constant ON_TOKEN_TRANSFER = 0xa4c0ed36; // onTokenTransfer(address,uint256,bytes) + + address internal bridgeContractAddr; + + constructor(string _name, string _symbol, uint8 _decimals) public DetailedERC20(_name, _symbol, _decimals) { + // solhint-disable-previous-line no-empty-blocks + } + + function bridgeContract() external view returns (address) { + return bridgeContractAddr; + } + + function setBridgeContract(address _bridgeContract) external onlyOwner { + require(AddressUtils.isContract(_bridgeContract)); + bridgeContractAddr = _bridgeContract; + } + + modifier validRecipient(address _recipient) { + require(_recipient != address(0) && _recipient != address(this)); + /* solcov ignore next */ + _; + } + + function transferAndCall(address _to, uint256 _value, bytes _data) external validRecipient(_to) returns (bool) { + require(superTransfer(_to, _value)); + emit Transfer(msg.sender, _to, _value, _data); + + if (AddressUtils.isContract(_to)) { + require(contractFallback(msg.sender, _to, _value, _data)); + } + return true; + } + + function getTokenInterfacesVersion() external pure returns (uint64 major, uint64 minor, uint64 patch) { + return (2, 5, 0); + } + + function superTransfer(address _to, uint256 _value) internal returns (bool) { + return super.transfer(_to, _value); + } + + function transfer(address _to, uint256 _value) public returns (bool) { + require(superTransfer(_to, _value)); + callAfterTransfer(msg.sender, _to, _value); + return true; + } + + function transferFrom(address _from, address _to, uint256 _value) public returns (bool) { + require(super.transferFrom(_from, _to, _value)); + callAfterTransfer(_from, _to, _value); + 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 (isBridge(_to)) { + require(contractFallback(_from, _to, _value, new bytes(0))); + } + } + + function isBridge(address _address) public view returns (bool) { + return _address == bridgeContractAddr; + } + + /** + * @dev call onTokenTransfer fallback on the token recipient contract + * @param _from tokens sender + * @param _to tokens recipient + * @param _value amount of tokens that was sent + * @param _data set of extra bytes that can be passed to the recipient + */ + function contractFallback(address _from, address _to, uint256 _value, bytes _data) private returns (bool) { + return _to.call(abi.encodeWithSelector(ON_TOKEN_TRANSFER, _from, _value, _data)); + } + + function finishMinting() public returns (bool) { + revert(); + } + + function renounceOwnership() public onlyOwner { + revert(); + } + + /** + * @dev Withdraws the erc20 tokens or native coins from this contract. + * @param _token address of the claimed token or address(0) for native coins. + * @param _to address of the tokens/coins receiver. + */ + function claimTokens(address _token, address _to) external onlyOwner { + claimValues(_token, _to); + } + + function increaseAllowance(address spender, uint256 addedValue) public returns (bool) { + return super.increaseApproval(spender, addedValue); + } + + function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) { + return super.decreaseApproval(spender, subtractedValue); + } +} + From 6b68a49f85c138bca1a4b5a3f1dd8e6a7ec5092d Mon Sep 17 00:00:00 2001 From: dapplion <35266934+dapplion@users.noreply.github.com> Date: Wed, 3 Apr 2024 15:42:38 +0900 Subject: [PATCH 2/2] Modify into ERC677BridgeFixedSupplyToken --- contracts/ERC677BridgeFixedSupplyToken.sol | 26 ++++++++++++++++------ 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/contracts/ERC677BridgeFixedSupplyToken.sol b/contracts/ERC677BridgeFixedSupplyToken.sol index ba49255fe..55e9ad675 100644 --- a/contracts/ERC677BridgeFixedSupplyToken.sol +++ b/contracts/ERC677BridgeFixedSupplyToken.sol @@ -1,7 +1,5 @@ pragma solidity 0.4.24; -import "openzeppelin-solidity/contracts/token/ERC20/BurnableToken.sol"; -import "openzeppelin-solidity/contracts/token/ERC20/MintableToken.sol"; import "openzeppelin-solidity/contracts/token/ERC20/DetailedERC20.sol"; import "openzeppelin-solidity/contracts/AddressUtils.sol"; import "./interfaces/IBurnableMintableERC677Token.sol"; @@ -11,7 +9,7 @@ import "./upgradeable_contracts/Claimable.sol"; * @title ERC677BridgeToken * @dev The basic implementation of a bridgeable ERC677-compatible token */ -contract ERC677BridgeToken is IBurnableMintableERC677Token, DetailedERC20, BurnableToken, MintableToken, Claimable { +contract ERC677BridgeFixedSupplyToken is IBurnableMintableERC677Token, DetailedERC20, Claimable { bytes4 internal constant ON_TOKEN_TRANSFER = 0xa4c0ed36; // onTokenTransfer(address,uint256,bytes) address internal bridgeContractAddr; @@ -94,10 +92,6 @@ contract ERC677BridgeToken is IBurnableMintableERC677Token, DetailedERC20, Burna return _to.call(abi.encodeWithSelector(ON_TOKEN_TRANSFER, _from, _value, _data)); } - function finishMinting() public returns (bool) { - revert(); - } - function renounceOwnership() public onlyOwner { revert(); } @@ -118,5 +112,23 @@ contract ERC677BridgeToken is IBurnableMintableERC677Token, DetailedERC20, Burna function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) { return super.decreaseApproval(spender, subtractedValue); } + + /** + * @dev No-op burn function, caller keeps the tokens + * @param _value + */ + function burn(uint256 _value) public { + // no-op + } + + /** + * @dev Pass-through function to transfer + * @param _to The address that will receive the tokens. + * @param _amount The amount of tokens to transfer. + * @return A boolean that indicates if the operation was successful. + */ + function mint(address _to, uint256 _amount) public returns (bool) { + return transfer(_to, _amount); + } }