-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add mintable burnable kitty contract * Add mediators contracts * Update flatten script * Add mediator deploy scripts * Add poa-bridge-contracts submodule
- Loading branch information
Showing
34 changed files
with
2,278 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,19 @@ | ||
DEPLOYMENT_ACCOUNT_PRIVATE_KEY=67..14 | ||
DEPLOYMENT_GAS_LIMIT_EXTRA=0.2 | ||
|
||
HOME_RPC_URL=https://sokol.poa.network | ||
HOME_DEPLOYMENT_GAS_PRICE=1000000000 | ||
HOME_AMB_BRIDGE=0x0000000000000000000000000000000000000000 | ||
HOME_MEDIATOR_REQUEST_GAS_LIMIT=1000000 | ||
HOME_MEDIATOR_OWNER=0x0000000000000000000000000000000000000000 | ||
HOME_UPGRADEABLE_ADMIN=0x0000000000000000000000000000000000000000 | ||
|
||
FOREIGN_RPC_URL=https://sokol.poa.network | ||
FOREIGN_DEPLOYMENT_GAS_PRICE=1000000000 | ||
FOREIGN_AMB_BRIDGE=0x0000000000000000000000000000000000000000 | ||
FOREIGN_MEDIATOR_REQUEST_GAS_LIMIT=1000000 | ||
FOREIGN_MEDIATOR_OWNER=0x0000000000000000000000000000000000000000 | ||
FOREIGN_UPGRADEABLE_ADMIN=0x0000000000000000000000000000000000000000 | ||
|
||
CRYPTOKITTIES_ADDRESS=0x0000000000000000000000000000000000000000 | ||
KITTIES_AMOUNT=1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
bridge-contracts |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,21 @@ | ||
{ | ||
"extends": ["plugin:node/recommended", "airbnb-base", "plugin:prettier/recommended"], | ||
"plugins": ["node"], | ||
"env": { | ||
"mocha": true | ||
}, | ||
"globals": { | ||
"artifacts": false, | ||
"contract": false, | ||
"web3": false | ||
}, | ||
"rules": { | ||
"no-await-in-loop": "off", | ||
"consistent-return": "off", | ||
"no-console": "off", | ||
"no-plusplus": "off", | ||
"no-use-before-define": ["error", { "functions": false }], | ||
"node/no-unpublished-require": "off" | ||
"node/no-unpublished-require": "off", | ||
"func-names": "off" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
[submodule "bridge-contracts"] | ||
path = bridge-contracts | ||
url = https://github.com/poanetwork/poa-bridge-contracts.git |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Submodule bridge-contracts
added at
86b35f
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
pragma solidity 0.4.24; | ||
|
||
interface IForeignMediator { | ||
function handleBridgedTokens(address _recipient, uint256 _tokenId, bytes32 _nonce) external; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
pragma solidity 0.4.24; | ||
|
||
interface IHomeMediator { | ||
function handleBridgedTokens(address _recipient, uint256 _tokenId, bytes _metadata, bytes32 _nonce) external; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
pragma solidity 0.4.24; | ||
|
||
interface ISimpleBridgeKitty { | ||
function mint( | ||
uint256 _tokenId, | ||
bool _isReady, | ||
uint256 _cooldownIndex, | ||
uint256 _nextActionAt, | ||
uint256 _siringWithId, | ||
uint256 _birthTime, | ||
uint256 _matronId, | ||
uint256 _sireId, | ||
uint256 _generation, | ||
uint256 _genes, | ||
address _owner | ||
) external; | ||
function burn(uint256 _tokenId) external; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
pragma solidity 0.4.24; | ||
|
||
import "../../bridge-contracts/contracts/upgradeability/EternalStorage.sol"; | ||
import "../../bridge-contracts/contracts/interfaces/IAMB.sol"; | ||
import "../../bridge-contracts/contracts/upgradeable_contracts/Ownable.sol"; | ||
import "openzeppelin-solidity/contracts/AddressUtils.sol"; | ||
|
||
contract AMBMediator is EternalStorage, Ownable { | ||
bytes32 internal constant BRIDGE_CONTRACT = keccak256(abi.encodePacked("bridgeContract")); | ||
bytes32 internal constant MEDIATOR_CONTRACT = keccak256(abi.encodePacked("mediatorContract")); | ||
bytes32 internal constant REQUEST_GAS_LIMIT = keccak256(abi.encodePacked("requestGasLimit")); | ||
|
||
function setBridgeContract(address _bridgeContract) external onlyOwner { | ||
_setBridgeContract(_bridgeContract); | ||
} | ||
|
||
function _setBridgeContract(address _bridgeContract) internal { | ||
require(AddressUtils.isContract(_bridgeContract)); | ||
addressStorage[BRIDGE_CONTRACT] = _bridgeContract; | ||
} | ||
|
||
function bridgeContract() public view returns (IAMB) { | ||
return IAMB(addressStorage[BRIDGE_CONTRACT]); | ||
} | ||
|
||
function setMediatorContractOnOtherSide(address _mediatorContract) external onlyOwner { | ||
_setMediatorContractOnOtherSide(_mediatorContract); | ||
} | ||
|
||
function _setMediatorContractOnOtherSide(address _mediatorContract) internal { | ||
addressStorage[MEDIATOR_CONTRACT] = _mediatorContract; | ||
} | ||
|
||
function mediatorContractOnOtherSide() public view returns (address) { | ||
return addressStorage[MEDIATOR_CONTRACT]; | ||
} | ||
|
||
function setRequestGasLimit(uint256 _requestGasLimit) external onlyOwner { | ||
_setRequestGasLimit(_requestGasLimit); | ||
} | ||
|
||
function _setRequestGasLimit(uint256 _requestGasLimit) internal { | ||
require(_requestGasLimit <= bridgeContract().maxGasPerTx()); | ||
uintStorage[REQUEST_GAS_LIMIT] = _requestGasLimit; | ||
} | ||
|
||
function requestGasLimit() public view returns (uint256) { | ||
return uintStorage[REQUEST_GAS_LIMIT]; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
pragma solidity 0.4.24; | ||
|
||
import "../../bridge-contracts/contracts/upgradeable_contracts/Initializable.sol"; | ||
import "../../bridge-contracts/contracts/upgradeable_contracts/Claimable.sol"; | ||
import "../../bridge-contracts/contracts/upgradeable_contracts/Upgradeable.sol"; | ||
import "../../bridge-contracts/contracts/libraries/Bytes.sol"; | ||
import "./AMBMediator.sol"; | ||
import "./ERC721Bridge.sol"; | ||
|
||
contract BasicMediator is Initializable, AMBMediator, ERC721Bridge, Upgradeable, Claimable { | ||
event FailedMessageFixed(bytes32 indexed dataHash, address recipient, uint256 tokenId); | ||
|
||
bytes32 internal constant NONCE = keccak256(abi.encodePacked("nonce")); | ||
bytes4 internal constant GET_KITTY = 0xe98b7f4d; // getKitty(uint256) | ||
|
||
function initialize( | ||
address _bridgeContract, | ||
address _mediatorContract, | ||
address _erc721token, | ||
uint256 _requestGasLimit, | ||
address _owner | ||
) external returns (bool) { | ||
require(!isInitialized()); | ||
|
||
_setBridgeContract(_bridgeContract); | ||
_setMediatorContractOnOtherSide(_mediatorContract); | ||
setErc721token(_erc721token); | ||
_setRequestGasLimit(_requestGasLimit); | ||
setOwner(_owner); | ||
setNonce(keccak256(abi.encodePacked(address(this)))); | ||
setInitialize(); | ||
|
||
return isInitialized(); | ||
} | ||
|
||
function getBridgeInterfacesVersion() external pure returns (uint64 major, uint64 minor, uint64 patch) { | ||
return (1, 0, 0); | ||
} | ||
|
||
function getBridgeMode() external pure returns (bytes4 _data) { | ||
return bytes4(keccak256(abi.encodePacked("nft-to-nft-amb"))); | ||
} | ||
|
||
function transferToken(address _from, uint256 _tokenId) external { | ||
ERC721 token = erc721token(); | ||
address to = address(this); | ||
|
||
token.transferFrom(_from, to, _tokenId); | ||
bridgeSpecificActionsOnTokenTransfer(_from, _tokenId); | ||
} | ||
|
||
/** | ||
* getKitty(uint256) returns: | ||
* bool isGestating, | ||
* bool isReady, | ||
* uint256 cooldownIndex, | ||
* uint256 nextActionAt, | ||
* uint256 siringWithId, | ||
* uint256 birthTime, | ||
* uint256 matronId, | ||
* uint256 sireId, | ||
* uint256 generation, | ||
* uint256 genes | ||
**/ | ||
function getMetadata(uint256 _tokenId) internal view returns (bytes memory metadata) { | ||
bytes memory callData = abi.encodeWithSelector(GET_KITTY, _tokenId); | ||
address tokenAddress = erc721token(); | ||
metadata = new bytes(320); | ||
assembly { | ||
let result := call(gas, tokenAddress, 0x0, add(callData, 0x20), mload(callData), 0, 0) | ||
returndatacopy(add(metadata, 0x20), 0, returndatasize) | ||
|
||
switch result | ||
case 0 { | ||
revert(0, 0) | ||
} | ||
} | ||
} | ||
|
||
function nonce() internal view returns (bytes32) { | ||
return Bytes.bytesToBytes32(bytesStorage[NONCE]); | ||
} | ||
|
||
function setNonce(bytes32 _hash) internal { | ||
bytesStorage[NONCE] = abi.encodePacked(_hash); | ||
} | ||
|
||
function setMessageHashTokenId(bytes32 _hash, uint256 _tokenId) internal { | ||
uintStorage[keccak256(abi.encodePacked("messageHashTokenId", _hash))] = _tokenId; | ||
} | ||
|
||
function messageHashTokenId(bytes32 _hash) internal view returns (uint256) { | ||
return uintStorage[keccak256(abi.encodePacked("messageHashTokenId", _hash))]; | ||
} | ||
|
||
function setMessageHashRecipient(bytes32 _hash, address _recipient) internal { | ||
addressStorage[keccak256(abi.encodePacked("messageHashRecipient", _hash))] = _recipient; | ||
} | ||
|
||
function messageHashRecipient(bytes32 _hash) internal view returns (address) { | ||
return addressStorage[keccak256(abi.encodePacked("messageHashRecipient", _hash))]; | ||
} | ||
|
||
function setMessageHashFixed(bytes32 _hash) internal { | ||
boolStorage[keccak256(abi.encodePacked("messageHashFixed", _hash))] = true; | ||
} | ||
|
||
function messageHashFixed(bytes32 _hash) public view returns (bool) { | ||
return boolStorage[keccak256(abi.encodePacked("messageHashFixed", _hash))]; | ||
} | ||
|
||
function requestFailedMessageFix(bytes32 _txHash) external { | ||
require(!bridgeContract().messageCallStatus(_txHash)); | ||
require(bridgeContract().failedMessageReceiver(_txHash) == address(this)); | ||
require(bridgeContract().failedMessageSender(_txHash) == mediatorContractOnOtherSide()); | ||
bytes32 dataHash = bridgeContract().failedMessageDataHash(_txHash); | ||
|
||
bytes4 methodSelector = this.fixFailedMessage.selector; | ||
bytes memory data = abi.encodeWithSelector(methodSelector, dataHash); | ||
bridgeContract().requireToPassMessage(mediatorContractOnOtherSide(), data, requestGasLimit()); | ||
} | ||
|
||
function claimTokens(address _token, address _to) public onlyIfUpgradeabilityOwner validAddress(_to) { | ||
claimValues(_token, _to); | ||
} | ||
|
||
function fixFailedMessage(bytes32 _dataHash) external; | ||
|
||
function bridgeSpecificActionsOnTokenTransfer(address _from, uint256 _tokenId) internal; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
pragma solidity 0.4.24; | ||
|
||
import "../kitty/ERC721.sol"; | ||
import "openzeppelin-solidity/contracts/AddressUtils.sol"; | ||
import "../../bridge-contracts/contracts/upgradeability/EternalStorage.sol"; | ||
|
||
contract ERC721Bridge is EternalStorage { | ||
bytes32 internal constant ERC721_TOKEN = keccak256(abi.encodePacked("erc721token")); | ||
|
||
function erc721token() public view returns (ERC721) { | ||
return ERC721(addressStorage[ERC721_TOKEN]); | ||
} | ||
|
||
function setErc721token(address _token) internal { | ||
require(AddressUtils.isContract(_token)); | ||
addressStorage[ERC721_TOKEN] = _token; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
pragma solidity 0.4.24; | ||
|
||
import "./BasicMediator.sol"; | ||
import "../interfaces/IHomeMediator.sol"; | ||
|
||
contract ForeignMediator is BasicMediator { | ||
function passMessage(address _from, uint256 _tokenId) internal { | ||
bytes memory metadata = getMetadata(_tokenId); | ||
|
||
bytes4 methodSelector = IHomeMediator(0).handleBridgedTokens.selector; | ||
bytes memory data = abi.encodeWithSelector(methodSelector, _from, _tokenId, metadata, nonce()); | ||
|
||
bytes32 dataHash = keccak256(data); | ||
setMessageHashTokenId(dataHash, _tokenId); | ||
setMessageHashRecipient(dataHash, _from); | ||
setNonce(dataHash); | ||
|
||
bridgeContract().requireToPassMessage(mediatorContractOnOtherSide(), data, requestGasLimit()); | ||
} | ||
|
||
function handleBridgedTokens( | ||
address _recipient, | ||
uint256 _tokenId, | ||
bytes32 /* _nonce */ | ||
) external { | ||
require(msg.sender == address(bridgeContract())); | ||
require(bridgeContract().messageSender() == mediatorContractOnOtherSide()); | ||
erc721token().transfer(_recipient, _tokenId); | ||
} | ||
|
||
function bridgeSpecificActionsOnTokenTransfer(address _from, uint256 _tokenId) internal { | ||
passMessage(_from, _tokenId); | ||
} | ||
|
||
function fixFailedMessage(bytes32 _dataHash) external { | ||
require(msg.sender == address(bridgeContract())); | ||
require(bridgeContract().messageSender() == mediatorContractOnOtherSide()); | ||
require(!messageHashFixed(_dataHash)); | ||
|
||
address recipient = messageHashRecipient(_dataHash); | ||
uint256 tokenId = messageHashTokenId(_dataHash); | ||
|
||
setMessageHashFixed(_dataHash); | ||
erc721token().transfer(recipient, tokenId); | ||
|
||
emit FailedMessageFixed(_dataHash, recipient, tokenId); | ||
} | ||
} |
Oops, something went wrong.