From fdf77c0ac472a5e442032d47667abe8f09b0d8f6 Mon Sep 17 00:00:00 2001 From: John Guibas Date: Tue, 31 Jan 2023 17:13:29 -0800 Subject: [PATCH 1/4] Implement Ethereum to Gnosis messaging with TelepathyHomeValidator --- .../arbitrary_message/BasicAMB.sol | 66 +++++++++++++++++++ .../arbitrary_message/MessageDelivery.sol | 7 ++ .../telepathy/HomeValidator.sol | 23 +++++++ .../telepathy/Interfaces.sol | 3 + 4 files changed, 99 insertions(+) create mode 100644 contracts/upgradeable_contracts/telepathy/HomeValidator.sol create mode 100644 contracts/upgradeable_contracts/telepathy/Interfaces.sol diff --git a/contracts/upgradeable_contracts/arbitrary_message/BasicAMB.sol b/contracts/upgradeable_contracts/arbitrary_message/BasicAMB.sol index 6a8b11d05..baa1cad4c 100644 --- a/contracts/upgradeable_contracts/arbitrary_message/BasicAMB.sol +++ b/contracts/upgradeable_contracts/arbitrary_message/BasicAMB.sol @@ -12,6 +12,16 @@ contract BasicAMB is BasicBridge, VersionableAMB { bytes32 internal constant DESTINATION_CHAIN_ID_LENGTH = 0xfb792ae4ad11102b93f26a51b3749c2b3667f8b561566a4806d4989692811594; // keccak256(abi.encodePacked("destinationChainIdLength")) bytes32 internal constant ALLOW_REENTRANT_REQUESTS = 0xffa3a5a0e192028fc343362a39c5688e5a60819a4dc5ab3ee70c25bc25b78dd6; // keccak256(abi.encodePacked("allowReentrantRequests")) + bytes32 internal constant HOME_OMNIBRIDGE_AMB = keccak256(abi.encodePacked("homeOmnibridgeAMB")); + bytes32 internal constant FOREIGN_OMNIBRIDGE_AMB = keccak256(abi.encodePacked("foreignOmnibridgeAMB")); + + bytes32 internal constant HOME_TELEPATHY_SOURCE_AMB = keccak256(abi.encodePacked("homeTelepathySourceAMB")); + bytes32 internal constant HOME_TELEPATHY_TARGET_AMB = keccak256(abi.encodePacked("homeTelepathyTargetAMB")); + bytes32 internal constant FOREIGN_TELEPATHY_SOURCE_AMB = keccak256(abi.encodePacked("foreignTelepathySourceAMB")); + bytes32 internal constant FOREIGN_TELEPATHY_TARGET_AMB = keccak256(abi.encodePacked("foreignTelepathyTargetAMB")); + + bytes32 internal constant HOME_TELEPATHY_VALIDATOR = keccak256(abi.encodePacked("homeTelepathyValidator")); + /** * Initializes AMB contract * @param _sourceChainId chain id of a network where this contract is deployed @@ -191,4 +201,60 @@ contract BasicAMB is BasicBridge, VersionableAMB { function _isDestinationChainIdValid(uint256 _chainId) internal returns (bool res) { return _chainId == sourceChainId(); } + + function setHomeOmnibridgeAMB(address addr) external onlyOwner { + addressStorage[HOME_OMNIBRIDGE_AMB] = addr; + } + + function homeOmnibridgeAMB() public view returns (address) { + return addressStorage[HOME_OMNIBRIDGE_AMB]; + } + + function setForeignOmnibridgeAMB(address addr) external onlyOwner { + addressStorage[FOREIGN_OMNIBRIDGE_AMB] = addr; + } + + function foreignOmnibridgeAMB() public view returns (address) { + return addressStorage[FOREIGN_OMNIBRIDGE_AMB]; + } + + function setHomeTelepathySourceAMB(address addr) external onlyOwner { + addressStorage[HOME_TELEPATHY_SOURCE_AMB] = addr; + } + + function homeTelepathySourceAMB() public view returns (address) { + return addressStorage[HOME_TELEPATHY_SOURCE_AMB]; + } + + function setHomeTelepathyTargetAMB(address addr) external onlyOwner { + addressStorage[HOME_TELEPATHY_TARGET_AMB] = addr; + } + + function homeTelepathyTargetAMB() public view returns (address) { + return addressStorage[HOME_TELEPATHY_TARGET_AMB]; + } + + function setForeignTelepathySourceAMB(address addr) external onlyOwner { + addressStorage[FOREIGN_TELEPATHY_SOURCE_AMB] = addr; + } + + function foreignTelepathySourceAMB() public view returns (address) { + return addressStorage[FOREIGN_TELEPATHY_SOURCE_AMB]; + } + + function setForeignTelepathyTargetAMB(address addr) external onlyOwner { + addressStorage[FOREIGN_TELEPATHY_TARGET_AMB] = addr; + } + + function foreignTelepathyTargetAMB() public view returns (address) { + return addressStorage[FOREIGN_TELEPATHY_TARGET_AMB]; + } + + function setHomeTelepathyValidator(address addr) external onlyOwner { + addressStorage[HOME_TELEPATHY_VALIDATOR] = addr; + } + + function setHomeTelepathyValidator() public view returns (address) { + return addressStorage[HOME_TELEPATHY_VALIDATOR]; + } } diff --git a/contracts/upgradeable_contracts/arbitrary_message/MessageDelivery.sol b/contracts/upgradeable_contracts/arbitrary_message/MessageDelivery.sol index 1bff1d607..b858480ca 100644 --- a/contracts/upgradeable_contracts/arbitrary_message/MessageDelivery.sol +++ b/contracts/upgradeable_contracts/arbitrary_message/MessageDelivery.sol @@ -5,6 +5,8 @@ import "./BasicAMB.sol"; import "./MessageProcessor.sol"; import "../../libraries/ArbitraryMessage.sol"; import "../../libraries/Bytes.sol"; +import "../telepathy/Interfaces.sol"; + contract MessageDelivery is BasicAMB, MessageProcessor { using SafeMath for uint256; @@ -62,6 +64,11 @@ contract MessageDelivery is BasicAMB, MessageProcessor { bytes memory eventData = abi.encodePacked(header, _data); + uint16 destChainId = uint16(destinationChainId()); + address homeTelepathyValidator = homeTelepathyValidator(); + address foreignTelepathySourceAMB = foreignTelepathySourceAMB(); + ISourceAMB(foreignTelepathySourceAMB).send(homeTelepathyValidator, destChainId, _gas, eventData); + emitEventOnMessageRequest(_messageId, eventData); return _messageId; } diff --git a/contracts/upgradeable_contracts/telepathy/HomeValidator.sol b/contracts/upgradeable_contracts/telepathy/HomeValidator.sol new file mode 100644 index 000000000..da4e93855 --- /dev/null +++ b/contracts/upgradeable_contracts/telepathy/HomeValidator.sol @@ -0,0 +1,23 @@ +pragma solidity 0.4.24; + +interface IHomeOmnibridgeAMB { + function executeAffirmation(bytes message) external; +} + +contract TelepathyHomeValidator { + address telepathyTargetAMB; + address homeOmnibridgeAMB; + address foreignOmnibridgeAMB; + + constructor(address _telepathyTargetAMB, address _homeOmnibridgeAMB, address _foreignOmnibridgeAMB) { + telepathyTargetAMB = _telepathyTargetAMB; + homeOmnibridgeAMB = _homeOmnibridgeAMB; + foreignOmnibridgeAMB = _foreignOmnibridgeAMB; + } + + function receiveSuccinct(address srcAddress, bytes message) external { + require(msg.sender == telepathyTargetAMB, "Only Succinct AMB can call this function"); + require(srcAddress == otherSideAMB, "Only other side AMB can pass a message call to this contract."); + IHomeOmnibridgeAMB(homeOmnibridgeAMB).executeAffirmation(message); + } +} \ No newline at end of file diff --git a/contracts/upgradeable_contracts/telepathy/Interfaces.sol b/contracts/upgradeable_contracts/telepathy/Interfaces.sol new file mode 100644 index 000000000..477972e42 --- /dev/null +++ b/contracts/upgradeable_contracts/telepathy/Interfaces.sol @@ -0,0 +1,3 @@ +interface ISourceAMB { + function send(address receiver, uint16 chainId, uint256 gasLimit, bytes data) external returns (bytes32); +} \ No newline at end of file From 98996ec7157f6eff84ae3ac90524ec2060f2217d Mon Sep 17 00:00:00 2001 From: John Guibas Date: Tue, 31 Jan 2023 17:51:26 -0800 Subject: [PATCH 2/4] Implement Gnosis to Ethereum messaging --- .../arbitrary_message/BasicAMB.sol | 68 ++++--------------- .../arbitrary_message/BasicForeignAMB.sol | 5 ++ .../arbitrary_message/MessageDelivery.sol | 6 +- .../telepathy/ForeignApprover.sol | 20 ++++++ .../telepathy/HomeValidator.sol | 2 +- .../telepathy/Interfaces.sol | 6 +- 6 files changed, 49 insertions(+), 58 deletions(-) create mode 100644 contracts/upgradeable_contracts/telepathy/ForeignApprover.sol diff --git a/contracts/upgradeable_contracts/arbitrary_message/BasicAMB.sol b/contracts/upgradeable_contracts/arbitrary_message/BasicAMB.sol index baa1cad4c..cc65639dc 100644 --- a/contracts/upgradeable_contracts/arbitrary_message/BasicAMB.sol +++ b/contracts/upgradeable_contracts/arbitrary_message/BasicAMB.sol @@ -1,4 +1,4 @@ -pragma solidity 0.4.24; +ragma solidity 0.4.24; import "../BasicBridge.sol"; import "./VersionableAMB.sol"; @@ -12,15 +12,9 @@ contract BasicAMB is BasicBridge, VersionableAMB { bytes32 internal constant DESTINATION_CHAIN_ID_LENGTH = 0xfb792ae4ad11102b93f26a51b3749c2b3667f8b561566a4806d4989692811594; // keccak256(abi.encodePacked("destinationChainIdLength")) bytes32 internal constant ALLOW_REENTRANT_REQUESTS = 0xffa3a5a0e192028fc343362a39c5688e5a60819a4dc5ab3ee70c25bc25b78dd6; // keccak256(abi.encodePacked("allowReentrantRequests")) - bytes32 internal constant HOME_OMNIBRIDGE_AMB = keccak256(abi.encodePacked("homeOmnibridgeAMB")); - bytes32 internal constant FOREIGN_OMNIBRIDGE_AMB = keccak256(abi.encodePacked("foreignOmnibridgeAMB")); - - bytes32 internal constant HOME_TELEPATHY_SOURCE_AMB = keccak256(abi.encodePacked("homeTelepathySourceAMB")); - bytes32 internal constant HOME_TELEPATHY_TARGET_AMB = keccak256(abi.encodePacked("homeTelepathyTargetAMB")); - bytes32 internal constant FOREIGN_TELEPATHY_SOURCE_AMB = keccak256(abi.encodePacked("foreignTelepathySourceAMB")); - bytes32 internal constant FOREIGN_TELEPATHY_TARGET_AMB = keccak256(abi.encodePacked("foreignTelepathyTargetAMB")); - - bytes32 internal constant HOME_TELEPATHY_VALIDATOR = keccak256(abi.encodePacked("homeTelepathyValidator")); + bytes32 internal constant TELEPATHY_SOURCE_AMB = keccak256(abi.encodePacked("telepathySourceAMB")); + bytes32 internal constant TELEPATHY_AGENT = keccak256(abi.encodePacked("telepathyAgent")); + bytes32 internal constant OTHERSIDE_TELEPATHY_AGENT = keccak256(abi.encodePacked("othersideTelepathyAgent")); /** * Initializes AMB contract @@ -202,59 +196,27 @@ contract BasicAMB is BasicBridge, VersionableAMB { return _chainId == sourceChainId(); } - function setHomeOmnibridgeAMB(address addr) external onlyOwner { - addressStorage[HOME_OMNIBRIDGE_AMB] = addr; + function setTelepathySourceAMB(address addr) external onlyOwner { + addressStorage[TELEPATHY_SOURCE_AMB] = addr; } - function homeOmnibridgeAMB() public view returns (address) { + function telepathySourceAMB() public view returns (address) { return addressStorage[HOME_OMNIBRIDGE_AMB]; } - function setForeignOmnibridgeAMB(address addr) external onlyOwner { - addressStorage[FOREIGN_OMNIBRIDGE_AMB] = addr; - } - - function foreignOmnibridgeAMB() public view returns (address) { - return addressStorage[FOREIGN_OMNIBRIDGE_AMB]; - } - - function setHomeTelepathySourceAMB(address addr) external onlyOwner { - addressStorage[HOME_TELEPATHY_SOURCE_AMB] = addr; - } - - function homeTelepathySourceAMB() public view returns (address) { - return addressStorage[HOME_TELEPATHY_SOURCE_AMB]; - } - - function setHomeTelepathyTargetAMB(address addr) external onlyOwner { - addressStorage[HOME_TELEPATHY_TARGET_AMB] = addr; - } - - function homeTelepathyTargetAMB() public view returns (address) { - return addressStorage[HOME_TELEPATHY_TARGET_AMB]; - } - - function setForeignTelepathySourceAMB(address addr) external onlyOwner { - addressStorage[FOREIGN_TELEPATHY_SOURCE_AMB] = addr; - } - - function foreignTelepathySourceAMB() public view returns (address) { - return addressStorage[FOREIGN_TELEPATHY_SOURCE_AMB]; - } - - function setForeignTelepathyTargetAMB(address addr) external onlyOwner { - addressStorage[FOREIGN_TELEPATHY_TARGET_AMB] = addr; + function setTelepathyAgent(address addr) external onlyOwner { + addressStorage[TELEPATHY_AGENT] = addr; } - function foreignTelepathyTargetAMB() public view returns (address) { - return addressStorage[FOREIGN_TELEPATHY_TARGET_AMB]; + function telepathyAgent() public view returns (address) { + return addressStorage[TELEPATHY_AGENT]; } - function setHomeTelepathyValidator(address addr) external onlyOwner { - addressStorage[HOME_TELEPATHY_VALIDATOR] = addr; + function setOthersideTelepathyAgent(address addr) external onlyOwner { + addressStorage[OTHERSIDE_TELEPATHY_AGENT] = addr; } - function setHomeTelepathyValidator() public view returns (address) { - return addressStorage[HOME_TELEPATHY_VALIDATOR]; + function othersideTelepathyAgent() public view returns (address) { + return addressStorage[OTHERSIDE_TELEPATHY_AGENT]; } } diff --git a/contracts/upgradeable_contracts/arbitrary_message/BasicForeignAMB.sol b/contracts/upgradeable_contracts/arbitrary_message/BasicForeignAMB.sol index 08914573a..06735e452 100644 --- a/contracts/upgradeable_contracts/arbitrary_message/BasicForeignAMB.sol +++ b/contracts/upgradeable_contracts/arbitrary_message/BasicForeignAMB.sol @@ -5,6 +5,7 @@ import "../../libraries/ArbitraryMessage.sol"; import "./BasicAMB.sol"; import "./MessageDelivery.sol"; import "../MessageRelay.sol"; +import "../telepathy/Interfaces.sol"; contract BasicForeignAMB is BasicAMB, MessageRelay, MessageDelivery { /** @@ -25,6 +26,10 @@ contract BasicForeignAMB is BasicAMB, MessageRelay, MessageDelivery { (msgId, sender, executor, gasLimit, dataType, chainIds, data) = ArbitraryMessage.unpackData(_data); + address telepathyAgent = telepathyAgent(); + bytes32 messageId = keccak256(_data); + require(ITelepathyForeignApprover(telepathyAgent).approvals(messageId) == true); + _executeMessage(msgId, sender, executor, gasLimit, dataType, chainIds, data); } diff --git a/contracts/upgradeable_contracts/arbitrary_message/MessageDelivery.sol b/contracts/upgradeable_contracts/arbitrary_message/MessageDelivery.sol index b858480ca..1af4eae7e 100644 --- a/contracts/upgradeable_contracts/arbitrary_message/MessageDelivery.sol +++ b/contracts/upgradeable_contracts/arbitrary_message/MessageDelivery.sol @@ -65,9 +65,9 @@ contract MessageDelivery is BasicAMB, MessageProcessor { bytes memory eventData = abi.encodePacked(header, _data); uint16 destChainId = uint16(destinationChainId()); - address homeTelepathyValidator = homeTelepathyValidator(); - address foreignTelepathySourceAMB = foreignTelepathySourceAMB(); - ISourceAMB(foreignTelepathySourceAMB).send(homeTelepathyValidator, destChainId, _gas, eventData); + address othersideTelepathyAgent = othersideTelepathyAgent(); + address telepathySourceAMB = telepathySourceAMB(); + ISourceAMB(telepathySourceAMB).send(othersideTelepathyAgent, destChainId, _gas, eventData); emitEventOnMessageRequest(_messageId, eventData); return _messageId; diff --git a/contracts/upgradeable_contracts/telepathy/ForeignApprover.sol b/contracts/upgradeable_contracts/telepathy/ForeignApprover.sol new file mode 100644 index 000000000..2266805c5 --- /dev/null +++ b/contracts/upgradeable_contracts/telepathy/ForeignApprover.sol @@ -0,0 +1,20 @@ +pragma solidity 0.4.24; + +contract TelepathyForeignApprover { + address telepathyTargetAMB; + address homeOmnibridgeAMB; + + mapping(bytes32 => bool) public approvals; + + constructor(address _telepathyTargetAMB, address _homeOmnibridgeAMB) { + telepathyTargetAMB = _telepathyTargetAMB; + homeOmnibridgeAMB = _homeOmnibridgeAMB; + } + + function receiveSuccinct(address srcAddress, bytes message) external { + require(msg.sender == telepathyTargetAMB, "Only Succinct AMB can call this function"); + require(srcAddress == homeOmnibridgeAMB, "Only other side AMB can pass a message call to this contract."); + bytes32 messageId = keccak256(message); + approvals[messageId] = true; + } +} \ No newline at end of file diff --git a/contracts/upgradeable_contracts/telepathy/HomeValidator.sol b/contracts/upgradeable_contracts/telepathy/HomeValidator.sol index da4e93855..5726f4240 100644 --- a/contracts/upgradeable_contracts/telepathy/HomeValidator.sol +++ b/contracts/upgradeable_contracts/telepathy/HomeValidator.sol @@ -17,7 +17,7 @@ contract TelepathyHomeValidator { function receiveSuccinct(address srcAddress, bytes message) external { require(msg.sender == telepathyTargetAMB, "Only Succinct AMB can call this function"); - require(srcAddress == otherSideAMB, "Only other side AMB can pass a message call to this contract."); + require(srcAddress == foreignOmnibridgeAMB, "Only other side AMB can pass a message call to this contract."); IHomeOmnibridgeAMB(homeOmnibridgeAMB).executeAffirmation(message); } } \ No newline at end of file diff --git a/contracts/upgradeable_contracts/telepathy/Interfaces.sol b/contracts/upgradeable_contracts/telepathy/Interfaces.sol index 477972e42..6c6ae4fec 100644 --- a/contracts/upgradeable_contracts/telepathy/Interfaces.sol +++ b/contracts/upgradeable_contracts/telepathy/Interfaces.sol @@ -1,3 +1,7 @@ interface ISourceAMB { - function send(address receiver, uint16 chainId, uint256 gasLimit, bytes data) external returns (bytes32); + function send(address receiver, uint16 chainId, uint256 gasLimit, bytes memory data) external returns (bytes32); +} + +interface ITelepathyForeignApprover { + function approvals(bytes32 messageId) external returns (bool); } \ No newline at end of file From db8c383d0d1426fcef22e3d498c5f0a824f77023 Mon Sep 17 00:00:00 2001 From: John Guibas Date: Tue, 31 Jan 2023 18:04:25 -0800 Subject: [PATCH 3/4] Fix pragma typo --- contracts/upgradeable_contracts/arbitrary_message/BasicAMB.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/upgradeable_contracts/arbitrary_message/BasicAMB.sol b/contracts/upgradeable_contracts/arbitrary_message/BasicAMB.sol index cc65639dc..2056d0056 100644 --- a/contracts/upgradeable_contracts/arbitrary_message/BasicAMB.sol +++ b/contracts/upgradeable_contracts/arbitrary_message/BasicAMB.sol @@ -1,4 +1,4 @@ -ragma solidity 0.4.24; +pragma solidity 0.4.24; import "../BasicBridge.sol"; import "./VersionableAMB.sol"; From cef3aed04e129d9202c43bb5533a1c3b40e59bc4 Mon Sep 17 00:00:00 2001 From: John Guibas Date: Mon, 6 Feb 2023 09:50:38 -0800 Subject: [PATCH 4/4] Fixed deployment system --- .../arbitrary_message/BasicAMB.sol | 14 +-- .../arbitrary_message/BasicForeignAMB.sol | 4 +- .../arbitrary_message/MessageDelivery.sol | 4 +- .../telepathy/ForeignApprover.sol | 21 ++-- .../telepathy/HomeValidator.sol | 21 ++-- .../telepathy/Interfaces.sol | 8 +- deploy/deploy.js | 1 + deploy/postDeploy.js | 103 ++++++++++++++++++ deploy/src/arbitrary_message/approver.js | 25 +++++ deploy/src/arbitrary_message/foreign.js | 6 +- deploy/src/arbitrary_message/home.js | 6 +- deploy/src/arbitrary_message/validator.js | 25 +++++ deploy/src/loadContracts.js | 4 +- 13 files changed, 207 insertions(+), 35 deletions(-) create mode 100644 deploy/postDeploy.js create mode 100644 deploy/src/arbitrary_message/approver.js create mode 100644 deploy/src/arbitrary_message/validator.js diff --git a/contracts/upgradeable_contracts/arbitrary_message/BasicAMB.sol b/contracts/upgradeable_contracts/arbitrary_message/BasicAMB.sol index 2056d0056..a4dfffbe1 100644 --- a/contracts/upgradeable_contracts/arbitrary_message/BasicAMB.sol +++ b/contracts/upgradeable_contracts/arbitrary_message/BasicAMB.sol @@ -12,9 +12,9 @@ contract BasicAMB is BasicBridge, VersionableAMB { bytes32 internal constant DESTINATION_CHAIN_ID_LENGTH = 0xfb792ae4ad11102b93f26a51b3749c2b3667f8b561566a4806d4989692811594; // keccak256(abi.encodePacked("destinationChainIdLength")) bytes32 internal constant ALLOW_REENTRANT_REQUESTS = 0xffa3a5a0e192028fc343362a39c5688e5a60819a4dc5ab3ee70c25bc25b78dd6; // keccak256(abi.encodePacked("allowReentrantRequests")) - bytes32 internal constant TELEPATHY_SOURCE_AMB = keccak256(abi.encodePacked("telepathySourceAMB")); - bytes32 internal constant TELEPATHY_AGENT = keccak256(abi.encodePacked("telepathyAgent")); - bytes32 internal constant OTHERSIDE_TELEPATHY_AGENT = keccak256(abi.encodePacked("othersideTelepathyAgent")); + bytes32 internal constant TELEPATHY_SOURCE_AMB = bytes32(0); + bytes32 internal constant TELEPATHY_AGENT = bytes32(1); + bytes32 internal constant OTHERSIDE_TELEPATHY_AGENT = bytes32(2); /** * Initializes AMB contract @@ -200,15 +200,15 @@ contract BasicAMB is BasicBridge, VersionableAMB { addressStorage[TELEPATHY_SOURCE_AMB] = addr; } - function telepathySourceAMB() public view returns (address) { - return addressStorage[HOME_OMNIBRIDGE_AMB]; + function getTelepathySourceAMB() public view returns (address) { + return addressStorage[TELEPATHY_SOURCE_AMB]; } function setTelepathyAgent(address addr) external onlyOwner { addressStorage[TELEPATHY_AGENT] = addr; } - function telepathyAgent() public view returns (address) { + function getTelepathyAgent() public view returns (address) { return addressStorage[TELEPATHY_AGENT]; } @@ -216,7 +216,7 @@ contract BasicAMB is BasicBridge, VersionableAMB { addressStorage[OTHERSIDE_TELEPATHY_AGENT] = addr; } - function othersideTelepathyAgent() public view returns (address) { + function getOthersideTelepathyAgent() public view returns (address) { return addressStorage[OTHERSIDE_TELEPATHY_AGENT]; } } diff --git a/contracts/upgradeable_contracts/arbitrary_message/BasicForeignAMB.sol b/contracts/upgradeable_contracts/arbitrary_message/BasicForeignAMB.sol index 06735e452..40162d800 100644 --- a/contracts/upgradeable_contracts/arbitrary_message/BasicForeignAMB.sol +++ b/contracts/upgradeable_contracts/arbitrary_message/BasicForeignAMB.sol @@ -26,9 +26,9 @@ contract BasicForeignAMB is BasicAMB, MessageRelay, MessageDelivery { (msgId, sender, executor, gasLimit, dataType, chainIds, data) = ArbitraryMessage.unpackData(_data); - address telepathyAgent = telepathyAgent(); + address telepathyAgent = getTelepathyAgent(); bytes32 messageId = keccak256(_data); - require(ITelepathyForeignApprover(telepathyAgent).approvals(messageId) == true); + require(ITelepathyForeignApprover(telepathyAgent).isApproved(messageId)); _executeMessage(msgId, sender, executor, gasLimit, dataType, chainIds, data); } diff --git a/contracts/upgradeable_contracts/arbitrary_message/MessageDelivery.sol b/contracts/upgradeable_contracts/arbitrary_message/MessageDelivery.sol index 1af4eae7e..74ec66565 100644 --- a/contracts/upgradeable_contracts/arbitrary_message/MessageDelivery.sol +++ b/contracts/upgradeable_contracts/arbitrary_message/MessageDelivery.sol @@ -65,8 +65,8 @@ contract MessageDelivery is BasicAMB, MessageProcessor { bytes memory eventData = abi.encodePacked(header, _data); uint16 destChainId = uint16(destinationChainId()); - address othersideTelepathyAgent = othersideTelepathyAgent(); - address telepathySourceAMB = telepathySourceAMB(); + address telepathySourceAMB = getTelepathySourceAMB(); + address othersideTelepathyAgent = getOthersideTelepathyAgent(); ISourceAMB(telepathySourceAMB).send(othersideTelepathyAgent, destChainId, _gas, eventData); emitEventOnMessageRequest(_messageId, eventData); diff --git a/contracts/upgradeable_contracts/telepathy/ForeignApprover.sol b/contracts/upgradeable_contracts/telepathy/ForeignApprover.sol index 2266805c5..64e557360 100644 --- a/contracts/upgradeable_contracts/telepathy/ForeignApprover.sol +++ b/contracts/upgradeable_contracts/telepathy/ForeignApprover.sol @@ -1,20 +1,27 @@ pragma solidity 0.4.24; contract TelepathyForeignApprover { - address telepathyTargetAMB; - address homeOmnibridgeAMB; - + bool public initialized = false; + address public foreignTelepathyReceiver; + address public homeOmnibridgeAMB; mapping(bytes32 => bool) public approvals; - constructor(address _telepathyTargetAMB, address _homeOmnibridgeAMB) { - telepathyTargetAMB = _telepathyTargetAMB; + function initialize(address _foreignTelepathyReceiver, address _homeOmnibridgeAMB) external { + require(!initialized); + foreignTelepathyReceiver = _foreignTelepathyReceiver; homeOmnibridgeAMB = _homeOmnibridgeAMB; + initialized = true; + } + + function isApproved(bytes32 messageId) public view returns (bool) { + return approvals[messageId]; } function receiveSuccinct(address srcAddress, bytes message) external { - require(msg.sender == telepathyTargetAMB, "Only Succinct AMB can call this function"); - require(srcAddress == homeOmnibridgeAMB, "Only other side AMB can pass a message call to this contract."); + require(msg.sender == foreignTelepathyReceiver); + require(srcAddress == homeOmnibridgeAMB); bytes32 messageId = keccak256(message); approvals[messageId] = true; } +} } \ No newline at end of file diff --git a/contracts/upgradeable_contracts/telepathy/HomeValidator.sol b/contracts/upgradeable_contracts/telepathy/HomeValidator.sol index 5726f4240..fadd891df 100644 --- a/contracts/upgradeable_contracts/telepathy/HomeValidator.sol +++ b/contracts/upgradeable_contracts/telepathy/HomeValidator.sol @@ -1,23 +1,24 @@ pragma solidity 0.4.24; -interface IHomeOmnibridgeAMB { - function executeAffirmation(bytes message) external; -} +import "./Interfaces.sol"; contract TelepathyHomeValidator { - address telepathyTargetAMB; - address homeOmnibridgeAMB; - address foreignOmnibridgeAMB; + bool public initialized = false; + address public homeTelepathyReceiver; + address public homeOmnibridgeAMB; + address public foreignOmnibridgeAMB; - constructor(address _telepathyTargetAMB, address _homeOmnibridgeAMB, address _foreignOmnibridgeAMB) { - telepathyTargetAMB = _telepathyTargetAMB; + function initialize(address _homeTelepathyReceiver, address _homeOmnibridgeAMB, address _foreignOmnibridgeAMB) { + require(!initialized); + homeTelepathyReceiver = _homeTelepathyReceiver; homeOmnibridgeAMB = _homeOmnibridgeAMB; foreignOmnibridgeAMB = _foreignOmnibridgeAMB; + initialized = true; } function receiveSuccinct(address srcAddress, bytes message) external { - require(msg.sender == telepathyTargetAMB, "Only Succinct AMB can call this function"); - require(srcAddress == foreignOmnibridgeAMB, "Only other side AMB can pass a message call to this contract."); + require(msg.sender == homeTelepathyReceiver); + require(srcAddress == foreignOmnibridgeAMB); IHomeOmnibridgeAMB(homeOmnibridgeAMB).executeAffirmation(message); } } \ No newline at end of file diff --git a/contracts/upgradeable_contracts/telepathy/Interfaces.sol b/contracts/upgradeable_contracts/telepathy/Interfaces.sol index 6c6ae4fec..b742f0b0e 100644 --- a/contracts/upgradeable_contracts/telepathy/Interfaces.sol +++ b/contracts/upgradeable_contracts/telepathy/Interfaces.sol @@ -1,7 +1,11 @@ interface ISourceAMB { - function send(address receiver, uint16 chainId, uint256 gasLimit, bytes memory data) external returns (bytes32); + function send(address receiver, uint16 chainId, uint256 gasLimit, bytes data) external returns (bytes32); } interface ITelepathyForeignApprover { - function approvals(bytes32 messageId) external returns (bool); + function isApproved(bytes32 messageId) external returns (bool); +} + +interface IHomeOmnibridgeAMB { + function executeAffirmation(bytes message) external; } \ No newline at end of file diff --git a/deploy/deploy.js b/deploy/deploy.js index 045beb2a5..65d8c9dcb 100644 --- a/deploy/deploy.js +++ b/deploy/deploy.js @@ -35,6 +35,7 @@ async function deployArbitraryMessage() { const preDeploy = require('./src/arbitrary_message/preDeploy') const deployHome = require('./src/arbitrary_message/home') const deployForeign = require('./src/arbitrary_message/foreign') + await preDeploy() const { homeBridge } = await deployHome() const { foreignBridge } = await deployForeign() diff --git a/deploy/postDeploy.js b/deploy/postDeploy.js new file mode 100644 index 000000000..f8f91b29d --- /dev/null +++ b/deploy/postDeploy.js @@ -0,0 +1,103 @@ +const assert = require('assert') +const Web3Utils = require('web3-utils') + +const env = require('../loadEnv') +const { privateKeyToAddress, sendRawTxHome } = require('../deploymentUtils') +const { web3Home, web3Foreign, deploymentPrivateKey, HOME_RPC_URL, FOREIGN_RPC_URL } = require('../web3') + +const { + homeContracts: { HomeAMB: HomeBridge, ForeignAMB: ForeignBridge } +} = require('../loadContracts') + +const { DEPLOYMENT_ACCOUNT_PRIVATE_KEY } = env + +const DEPLOYMENT_ACCOUNT_ADDRESS = privateKeyToAddress(DEPLOYMENT_ACCOUNT_PRIVATE_KEY) + +async function executeTransactions({ bridge, initialNonce, succinctAddress, otherAMBAddress, RPC_URL }) { + let nonce = initialNonce + + const setSuccinctData = await bridge.methods + .setSuccinctAMBAddress(succinctAddress) + .encodeABI({ from: DEPLOYMENT_ACCOUNT_ADDRESS }) + console.log('Setting Succinct Address') + console.log({ + data: setSuccinctData, + nonce, + to: bridge.options.address, + privateKey: deploymentPrivateKey, + url: RPC_URL + }) + const setSuccinctTx = await sendRawTxHome({ + data: setSuccinctData, + nonce, + to: bridge.options.address, + privateKey: deploymentPrivateKey, + url: RPC_URL + }) + if (setSuccinctTx.status) { + assert.strictEqual(Web3Utils.hexToNumber(setSuccinctTx.status), 1, 'Transaction Failed') + } else { + console.log('Transaction failed') + // await assertStateWithRetry(bridge.methods.isInitialized().call, true) + } + nonce++ + const setOtherAMBData = await bridge.methods + .setOtherSideAMBAddress(otherAMBAddress) + .encodeABI({ from: DEPLOYMENT_ACCOUNT_ADDRESS }) + console.log('Setting other side AMB address') + const setOtherAMBTx = await sendRawTxHome({ + data: setOtherAMBData, + nonce, + to: bridge.options.address, + privateKey: deploymentPrivateKey, + url: RPC_URL + }) + if (setOtherAMBTx.status) { + assert.strictEqual(Web3Utils.hexToNumber(setOtherAMBTx.status), 1, 'Transaction Failed') + } else { + console.log('Transaction failed') + // await assertStateWithRetry(bridge.methods.isInitialized().call, true) + } + return nonce +} + +async function main() { + console.log('============================================') + console.log('Running post-deployment setting of variables') + console.log('============================================\n') + + const SUCCINCT_HOME_SOURCE_AMB_ADDRESS = '0xd667A279A51fE457f934A5c487FC490B91A77d1a'; + const SUCCINCT_HOME_TARGET_AMB_ADDRESS = '0xef604f14B99a37bf88F239C85A8826AeB2D9D699'; + const SUCCINCT_FOREIGN_SOURCE_AMB_ADDRESS = '0x39323dC5A276553EF7fD16Ed3164175747eB254c'; + const SUCCINCT_FOREIGN_TARGET_AMB_ADDRESS = '0xbc394A38fD6a76F254d14886bCe053279eAffB46'; + + const HOME_TOKENBRIDGE_AMB = '0xFc8D4E3C19B42A9a1cb3B79f925e2382555ceE67' + const FOREIGN_TOKENBRIDGE_AMB = '0x058C1b0Cb334fEb31BcAb58e8f967d083eddf1be' + + let nonce = await web3Home.eth.getTransactionCount(DEPLOYMENT_ACCOUNT_ADDRESS) + const homeBridge = new web3Home.eth.Contract(HomeBridge.abi, { from: DEPLOYMENT_ACCOUNT_ADDRESS }) + homeBridge.options.address = HOME_TOKENBRIDGE_AMB + + console.log('Setting up addresses for home AMB') + await executeTransactions({ + bridge: homeBridge, + initialNonce: nonce, + succinctAddress: HOME_SUCCINCT_ADDRESS, + otherAMBAddress: FOREIGN_TOKENBRIDGE_AMB, + RPC_URL: HOME_RPC_URL + }) + + let foreignNonce = await web3Foreign.eth.getTransactionCount(DEPLOYMENT_ACCOUNT_ADDRESS) + const foreignBridge = new web3Foreign.eth.Contract(ForeignBridge.abi, { from: DEPLOYMENT_ACCOUNT_ADDRESS }) + foreignBridge.options.address = FOREIGN_TOKENBRIDGE_AMB + console.log('Setting up addresses for foreign AMB') + await executeTransactions({ + bridge: foreignBridge, + initialNonce: foreignNonce, + succinctAddress: FOREIGN_SUCCINCT_ADDRESS, + otherAMBAddress: HOME_TOKENBRIDGE_AMB, + RPC_URL: FOREIGN_RPC_URL + }) +} + +main() \ No newline at end of file diff --git a/deploy/src/arbitrary_message/approver.js b/deploy/src/arbitrary_message/approver.js new file mode 100644 index 000000000..775df8fec --- /dev/null +++ b/deploy/src/arbitrary_message/approver.js @@ -0,0 +1,25 @@ +const env = require('../loadEnv') +const { + deployContract, + privateKeyToAddress, +} = require('../deploymentUtils') +const { web3Home } = require('../web3') +const { homeContracts: { TelepathyForeignApprover } } = require('../loadContracts') +const { DEPLOYMENT_ACCOUNT_PRIVATE_KEY } = env + +const DEPLOYMENT_ACCOUNT_ADDRESS = privateKeyToAddress(DEPLOYMENT_ACCOUNT_PRIVATE_KEY) + +async function deployTelepathyForeignApprover() { + console.log('========================================') + console.log('Deploying Telepathy Foreign Approver') + console.log('========================================\n') + let nonce = await web3Home.eth.getTransactionCount(DEPLOYMENT_ACCOUNT_ADDRESS) + const telepathyForeignApprover = await deployContract(TelepathyForeignApprover, [], { + from: DEPLOYMENT_ACCOUNT_ADDRESS, + network: 'foreign', + nonce + }) + console.log('Telepathy Foreign Approver', telepathyForeignApprover.options.address) +} + +module.exports = deployTelepathyForeignApprover \ No newline at end of file diff --git a/deploy/src/arbitrary_message/foreign.js b/deploy/src/arbitrary_message/foreign.js index 91c20312e..b07da0df2 100644 --- a/deploy/src/arbitrary_message/foreign.js +++ b/deploy/src/arbitrary_message/foreign.js @@ -17,11 +17,11 @@ const { foreignContracts: { EternalStorageProxy, BridgeValidators, ForeignAMB: ForeignBridge } } = require('../loadContracts') -const VALIDATORS = env.VALIDATORS.split(' ') +const VALIDATORS = env.FOREIGN_VALIDATORS.split(' ') const { DEPLOYMENT_ACCOUNT_PRIVATE_KEY, - REQUIRED_NUMBER_OF_VALIDATORS, + FOREIGN_REQUIRED_NUMBER_OF_VALIDATORS, FOREIGN_GAS_PRICE, FOREIGN_BRIDGE_OWNER, FOREIGN_VALIDATORS_OWNER, @@ -30,6 +30,8 @@ const { FOREIGN_REQUIRED_BLOCK_CONFIRMATIONS } = env +const REQUIRED_NUMBER_OF_VALIDATORS = FOREIGN_REQUIRED_NUMBER_OF_VALIDATORS + const DEPLOYMENT_ACCOUNT_ADDRESS = privateKeyToAddress(DEPLOYMENT_ACCOUNT_PRIVATE_KEY) async function initializeBridge({ validatorsBridge, bridge, initialNonce }) { diff --git a/deploy/src/arbitrary_message/home.js b/deploy/src/arbitrary_message/home.js index 4087765f4..4a9f20fbb 100644 --- a/deploy/src/arbitrary_message/home.js +++ b/deploy/src/arbitrary_message/home.js @@ -17,11 +17,11 @@ const { homeContracts: { EternalStorageProxy, BridgeValidators, HomeAMB: HomeBridge } } = require('../loadContracts') -const VALIDATORS = env.VALIDATORS.split(' ') +const VALIDATORS = env.HOME_VALIDATORS.split(' ') const { DEPLOYMENT_ACCOUNT_PRIVATE_KEY, - REQUIRED_NUMBER_OF_VALIDATORS, + HOME_REQUIRED_NUMBER_OF_VALIDATORS, HOME_GAS_PRICE, HOME_BRIDGE_OWNER, HOME_VALIDATORS_OWNER, @@ -30,6 +30,8 @@ const { HOME_REQUIRED_BLOCK_CONFIRMATIONS } = env +const REQUIRED_NUMBER_OF_VALIDATORS = HOME_REQUIRED_NUMBER_OF_VALIDATORS + const DEPLOYMENT_ACCOUNT_ADDRESS = privateKeyToAddress(DEPLOYMENT_ACCOUNT_PRIVATE_KEY) async function initializeBridge({ validatorsBridge, bridge, initialNonce }) { diff --git a/deploy/src/arbitrary_message/validator.js b/deploy/src/arbitrary_message/validator.js new file mode 100644 index 000000000..bb3fd9d9d --- /dev/null +++ b/deploy/src/arbitrary_message/validator.js @@ -0,0 +1,25 @@ +const env = require('../loadEnv') +const { + deployContract, + privateKeyToAddress, +} = require('../deploymentUtils') +const { web3Home } = require('../web3') +const { homeContracts: { TelepathyHomeValidator } } = require('../loadContracts') +const { DEPLOYMENT_ACCOUNT_PRIVATE_KEY } = env + +const DEPLOYMENT_ACCOUNT_ADDRESS = privateKeyToAddress(DEPLOYMENT_ACCOUNT_PRIVATE_KEY) + +async function deployTelepathyHomeValidator() { + console.log('========================================') + console.log('Deploying Telepathy Home Validator') + console.log('========================================\n') + let nonce = await web3Home.eth.getTransactionCount(DEPLOYMENT_ACCOUNT_ADDRESS) + const telepathyForeignApprover = await deployContract(TelepathyHomeValidator, [], { + from: DEPLOYMENT_ACCOUNT_ADDRESS, + network: 'home', + nonce + }) + console.log('Telepathy Home Validator', telepathyForeignApprover.options.address) +} + +module.exports = deployTelepathyHomeValidator \ No newline at end of file diff --git a/deploy/src/loadContracts.js b/deploy/src/loadContracts.js index 509d556d6..f7793aa27 100644 --- a/deploy/src/loadContracts.js +++ b/deploy/src/loadContracts.js @@ -19,7 +19,9 @@ function getContracts() { HomeAMB: require(`../../build/${buildPath}/HomeAMB.json`), ForeignAMB: require(`../../build/${buildPath}/ForeignAMB`), HomeAMBErc677ToErc677: require(`../../build/${buildPath}/HomeAMBErc677ToErc677.json`), - ForeignAMBErc677ToErc677: require(`../../build/${buildPath}/ForeignAMBErc677ToErc677.json`) + ForeignAMBErc677ToErc677: require(`../../build/${buildPath}/ForeignAMBErc677ToErc677.json`), + TelepathyForeignApprover: require(`../../build/${buildPath}/TelepathyForeignApprover.json`), + TelepathyHomeValidator: require(`../../build/${buildPath}/TelepathyHomeValidator.json`) } }