Skip to content
This repository has been archived by the owner on May 9, 2024. It is now read-only.

Commit

Permalink
Merge fd511e5 into bd1021a
Browse files Browse the repository at this point in the history
  • Loading branch information
lastperson committed Nov 11, 2020
2 parents bd1021a + fd511e5 commit a8a8805
Show file tree
Hide file tree
Showing 14 changed files with 176 additions and 57 deletions.
15 changes: 8 additions & 7 deletions contracts/Bridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ contract Bridge is Pausable, AccessControl, SafeMath {
// destinationChainID + depositNonce => dataHash => relayerAddress => bool
mapping(uint72 => mapping(bytes32 => mapping(address => bool))) public _hasVotedOnProposal;

event RelayerThresholdChanged(uint indexed newThreshold);
event RelayerThresholdChanged(uint256 indexed newThreshold);
event RelayerAdded(address indexed relayer);
event RelayerRemoved(address indexed relayer);
event Deposit(
Expand Down Expand Up @@ -102,15 +102,15 @@ contract Bridge is Pausable, AccessControl, SafeMath {
@param initialRelayers Addresses that should be initially granted the relayer role.
@param initialRelayerThreshold Number of votes needed for a deposit proposal to be considered passed.
*/
constructor (uint8 chainID, address[] memory initialRelayers, uint initialRelayerThreshold, uint256 fee, uint256 expiry) public {
constructor (uint8 chainID, address[] memory initialRelayers, uint256 initialRelayerThreshold, uint256 fee, uint256 expiry) public {
_chainID = chainID;
_relayerThreshold = initialRelayerThreshold;
_fee = fee;
_expiry = expiry;

_setupRole(DEFAULT_ADMIN_ROLE, msg.sender);

for (uint i; i < initialRelayers.length; i++) {
for (uint256 i; i < initialRelayers.length; i++) {
grantRole(RELAYER_ROLE, initialRelayers[i]);
}

Expand Down Expand Up @@ -157,7 +157,7 @@ contract Bridge is Pausable, AccessControl, SafeMath {
@param newThreshold Value {_relayerThreshold} will be changed to.
@notice Emits {RelayerThresholdChanged} event.
*/
function adminChangeRelayerThreshold(uint newThreshold) external onlyAdmin {
function adminChangeRelayerThreshold(uint256 newThreshold) external onlyAdmin {
_relayerThreshold = newThreshold;
emit RelayerThresholdChanged(newThreshold);
}
Expand Down Expand Up @@ -215,11 +215,12 @@ contract Bridge is Pausable, AccessControl, SafeMath {
bytes32 resourceID,
address contractAddress,
bytes4 depositFunctionSig,
uint256 depositFunctionDepositerOffset,
bytes4 executeFunctionSig
) external onlyAdmin {
_resourceIDToHandlerAddress[resourceID] = handlerAddress;
IGenericHandler handler = IGenericHandler(handlerAddress);
handler.setResource(resourceID, contractAddress, depositFunctionSig, executeFunctionSig);
handler.setResource(resourceID, contractAddress, depositFunctionSig, depositFunctionDepositerOffset, executeFunctionSig);
}
/**
Expand Down Expand Up @@ -262,7 +263,7 @@ contract Bridge is Pausable, AccessControl, SafeMath {
@notice Only callable by admin.
@param newFee Value {_fee} will be updated to.
*/
function adminChangeFee(uint newFee) external onlyAdmin {
function adminChangeFee(uint256 newFee) external onlyAdmin {
require(_fee != newFee, "Current fee is equal to new fee");
_fee = newFee;
}
Expand Down Expand Up @@ -425,7 +426,7 @@ contract Bridge is Pausable, AccessControl, SafeMath {
@param amounts Array of amonuts to transfer to {addrs}.
*/
function transferFunds(address payable[] calldata addrs, uint[] calldata amounts) external onlyAdmin {
for (uint i = 0; i < addrs.length; i++) {
for (uint256 i = 0; i < addrs.length; i++) {
addrs[i].transfer(amounts[i]);
}
}
Expand Down
8 changes: 8 additions & 0 deletions contracts/TestContracts.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,11 @@ contract ThreeArguments {
emit ThreeArgumentsCalled(argumentOne, argumentTwo, argumentThree);
}
}

contract WithDepositer {
event WithDepositerCalled(address argumentOne, uint256 argumentTwo);

function withDepositer(address argumentOne, uint256 argumentTwo) external {
emit WithDepositerCalled(argumentOne, argumentTwo);
}
}
41 changes: 33 additions & 8 deletions contracts/handlers/GenericHandler.sol
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ contract GenericHandler is IGenericHandler {
// contract address => deposit function signature
mapping (address => bytes4) public _contractAddressToDepositFunctionSignature;

// contract address => depositer address position offset in the metadata
mapping (address => uint256) public _contractAddressToDepositFunctionDepositerOffset;

// contract address => execute proposal function signature
mapping (address => bytes4) public _contractAddressToExecuteFunctionSignature;

Expand All @@ -42,7 +45,7 @@ contract GenericHandler is IGenericHandler {
}

function _onlyBridge() private view {
require(msg.sender == _bridgeAddress, "sender must be bridge contract");
require(msg.sender == _bridgeAddress, "sender must be bridge contract");
}

/**
Expand All @@ -67,6 +70,7 @@ contract GenericHandler is IGenericHandler {
bytes32[] memory initialResourceIDs,
address[] memory initialContractAddresses,
bytes4[] memory initialDepositFunctionSignatures,
uint256[] memory initialDepositFunctionDepositerOffsets,
bytes4[] memory initialExecuteFunctionSignatures
) public {
require(initialResourceIDs.length == initialContractAddresses.length,
Expand All @@ -78,13 +82,17 @@ contract GenericHandler is IGenericHandler {
require(initialDepositFunctionSignatures.length == initialExecuteFunctionSignatures.length,
"provided deposit and execute function signatures len mismatch");

require(initialDepositFunctionDepositerOffsets.length == initialExecuteFunctionSignatures.length,
"provided depositer offsets and function signatures len mismatch");

_bridgeAddress = bridgeAddress;

for (uint256 i = 0; i < initialResourceIDs.length; i++) {
_setResource(
initialResourceIDs[i],
initialContractAddresses[i],
initialDepositFunctionSignatures[i],
initialDepositFunctionDepositerOffsets[i],
initialExecuteFunctionSignatures[i]);
}
}
Expand All @@ -108,28 +116,31 @@ contract GenericHandler is IGenericHandler {
then sets {_resourceIDToContractAddress} with {contractAddress},
{_contractAddressToResourceID} with {resourceID},
{_contractAddressToDepositFunctionSignature} with {depositFunctionSig},
{_contractAddressToDepositFunctionDepositerOffset} with {depositFunctionDepositerOffset},
{_contractAddressToExecuteFunctionSignature} with {executeFunctionSig},
and {_contractWhitelist} to true for {contractAddress}.
@param resourceID ResourceID to be used when making deposits.
@param contractAddress Address of contract to be called when a deposit is made and a deposited is executed.
@param depositFunctionSig Function signature of method to be called in {contractAddress} when a deposit is made.
@param depositFunctionDepositerOffset Depositer address position offset in the metadata, in bytes.
@param executeFunctionSig Function signature of method to be called in {contractAddress} when a deposit is executed.
*/
function setResource(
bytes32 resourceID,
address contractAddress,
bytes4 depositFunctionSig,
uint256 depositFunctionDepositerOffset,
bytes4 executeFunctionSig
) external onlyBridge override {

_setResource(resourceID, contractAddress, depositFunctionSig, executeFunctionSig);
_setResource(resourceID, contractAddress, depositFunctionSig, depositFunctionDepositerOffset, executeFunctionSig);
}

/**
@notice A deposit is initiatied by making a deposit in the Bridge contract.
@param destinationChainID Chain ID deposit is expected to be bridged to.
@param depositNonce This value is generated as an ID by the Bridge contract.
@param depositer Address of account making the deposit in the Bridge contract.
@param depositer Address of the account making deposit in the Bridge contract.
@param data Consists of: {resourceID}, {lenMetaData}, and {metaData} all padded to 32 bytes.
@notice Data passed into the function should be constructed as follows:
len(data) uint256 bytes 0 - 32
Expand All @@ -139,20 +150,32 @@ contract GenericHandler is IGenericHandler {
{metaData} is expected to consist of needed function arguments.
*/
function deposit(bytes32 resourceID, uint8 destinationChainID, uint64 depositNonce, address depositer, bytes calldata data) external onlyBridge {
uint lenMetadata;
uint256 lenMetadata;
bytes memory metadata;

lenMetadata = abi.decode(data, (uint));
lenMetadata = abi.decode(data, (uint256));
metadata = bytes(data[32:32 + lenMetadata]);

address contractAddress = _resourceIDToContractAddress[resourceID];
uint256 depositerOffset = _contractAddressToDepositFunctionDepositerOffset[contractAddress];
if (depositerOffset > 0) {
uint256 metadataDepositer;
// Skipping 32 bytes of length prefix and depositerOffset bytes.
assembly {
metadataDepositer := mload(add(add(metadata, 32), depositerOffset))
}
// metadataDepositer contains 0xdepositerAddressdepositerAddressdeposite************************
// Shift it 12 bytes right: 0x000000000000000000000000depositerAddressdepositerAddressdeposite
require(depositer == address(metadataDepositer >> 96), 'incorrect depositer in the data');
}

require(_contractWhitelist[contractAddress], "provided contractAddress is not whitelisted");

bytes4 sig = _contractAddressToDepositFunctionSignature[contractAddress];
if (sig != bytes4(0)) {
bytes memory callData = abi.encodePacked(sig, metadata);
(bool success,) = contractAddress.call(callData);
require(success, "delegatecall to contractAddress failed");
require(success, "call to contractAddress failed");
}

_depositRecords[destinationChainID][depositNonce] = DepositRecord(
Expand All @@ -174,10 +197,10 @@ contract GenericHandler is IGenericHandler {
{metaData} is expected to consist of needed function arguments.
*/
function executeProposal(bytes32 resourceID, bytes calldata data) external onlyBridge {
uint lenMetadata;
uint256 lenMetadata;
bytes memory metaData;

lenMetadata = abi.decode(data, (uint));
lenMetadata = abi.decode(data, (uint256));
metaData = bytes(data[32:32 + lenMetadata]);

address contractAddress = _resourceIDToContractAddress[resourceID];
Expand All @@ -195,11 +218,13 @@ contract GenericHandler is IGenericHandler {
bytes32 resourceID,
address contractAddress,
bytes4 depositFunctionSig,
uint256 depositFunctionDepositerOffset,
bytes4 executeFunctionSig
) internal {
_resourceIDToContractAddress[resourceID] = contractAddress;
_contractAddressToResourceID[contractAddress] = resourceID;
_contractAddressToDepositFunctionSignature[contractAddress] = depositFunctionSig;
_contractAddressToDepositFunctionDepositerOffset[contractAddress] = depositFunctionDepositerOffset;
_contractAddressToExecuteFunctionSignature[contractAddress] = executeFunctionSig;

_contractWhitelist[contractAddress] = true;
Expand Down
8 changes: 7 additions & 1 deletion contracts/interfaces/IGenericHandler.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@ interface IGenericHandler {
@param resourceID ResourceID to be used when making deposits.
@param contractAddress Address of contract to be called when a deposit is made and a deposited is executed.
@param depositFunctionSig Function signature of method to be called in {contractAddress} when a deposit is made.
@param depositFunctionDepositerOffset Depositer address position offset in the metadata, in bytes.
@param executeFunctionSig Function signature of method to be called in {contractAddress} when a deposit is executed.
*/
function setResource(bytes32 resourceID, address contractAddress, bytes4 depositFunctionSig, bytes4 executeFunctionSig) external;
function setResource(
bytes32 resourceID,
address contractAddress,
bytes4 depositFunctionSig,
uint depositFunctionDepositerOffset,
bytes4 executeFunctionSig) external;
}
6 changes: 3 additions & 3 deletions test/contractBridge/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,15 +139,15 @@ contract('Bridge - [admin]', async accounts => {
it('Should set a Generic Resource ID and contract address', async () => {
const CentrifugeAssetInstance = await CentrifugeAssetContract.new();
const resourceID = Helpers.createResourceID(CentrifugeAssetInstance.address, chainID);
const GenericHandlerInstance = await GenericHandlerContract.new(BridgeInstance.address, [], [], [], []);
const GenericHandlerInstance = await GenericHandlerContract.new(BridgeInstance.address, [], [], [], [], []);

await TruffleAssert.passes(BridgeInstance.adminSetGenericResource(GenericHandlerInstance.address, resourceID, CentrifugeAssetInstance.address, '0x00000000', '0x00000000'));
await TruffleAssert.passes(BridgeInstance.adminSetGenericResource(GenericHandlerInstance.address, resourceID, CentrifugeAssetInstance.address, '0x00000000', 0, '0x00000000'));
assert.equal(await GenericHandlerInstance._resourceIDToContractAddress.call(resourceID), CentrifugeAssetInstance.address);
assert.equal(await GenericHandlerInstance._contractAddressToResourceID.call(CentrifugeAssetInstance.address), resourceID.toLowerCase());
});

it('Should require admin role to set a Generic Resource ID and contract address', async () => {
await assertOnlyAdmin(BridgeInstance.adminSetGenericResource, someAddress, bytes32, someAddress, '0x00000000', '0x00000000');
await assertOnlyAdmin(BridgeInstance.adminSetGenericResource, someAddress, bytes32, someAddress, '0x00000000', 0, '0x00000000');
});

// Set burnable
Expand Down
5 changes: 4 additions & 1 deletion test/contractBridge/depositGeneric.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ contract('Bridge - [deposit - Generic]', async () => {
let initialResourceIDs;
let initialContractAddresses;
let initialDepositFunctionSignatures;
let initialDepositFunctionDepositerOffsets;
let initialExecuteFunctionSignatures;

beforeEach(async () => {
Expand All @@ -34,16 +35,18 @@ contract('Bridge - [deposit - Generic]', async () => {
initialResourceIDs = [resourceID];
initialContractAddresses = [CentrifugeAssetInstance.address];
initialDepositFunctionSignatures = [Helpers.blankFunctionSig];
initialDepositFunctionDepositerOffsets = [Helpers.blankFunctionDepositerOffset];
initialExecuteFunctionSignatures = [Helpers.getFunctionSignature(CentrifugeAssetInstance, 'store')];

GenericHandlerInstance = await GenericHandlerContract.new(
BridgeInstance.address,
initialResourceIDs,
initialContractAddresses,
initialDepositFunctionSignatures,
initialDepositFunctionDepositerOffsets,
initialExecuteFunctionSignatures);

await BridgeInstance.adminSetGenericResource(GenericHandlerInstance.address, resourceID, initialContractAddresses[0], initialDepositFunctionSignatures[0], initialExecuteFunctionSignatures[0]);
await BridgeInstance.adminSetGenericResource(GenericHandlerInstance.address, resourceID, initialContractAddresses[0], initialDepositFunctionSignatures[0], initialDepositFunctionDepositerOffsets[0], initialExecuteFunctionSignatures[0]);

depositData = Helpers.createGenericDepositData('0xdeadbeef');
});
Expand Down
6 changes: 5 additions & 1 deletion test/contractBridge/fee.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ contract('Bridge - [fee]', async (accounts) => {
const originChainID = 1;
const destinationChainID = 2;
const blankFunctionSig = '0x00000000';
const blankFunctionDepositerOffset = 0;
const relayer = accounts[0];

let BridgeInstance;
Expand All @@ -25,6 +26,7 @@ contract('Bridge - [fee]', async (accounts) => {
let initialResourceIDs;
let initialContractAddresses;
let initialDepositFunctionSignatures;
let initialDepositFunctionDepositerOffsets;
let initialExecuteFunctionSignatures;

beforeEach(async () => {
Expand All @@ -37,16 +39,18 @@ contract('Bridge - [fee]', async (accounts) => {
initialResourceIDs = [resourceID];
initialContractAddresses = [CentrifugeAssetInstance.address];
initialDepositFunctionSignatures = [blankFunctionSig];
initialDepositFunctionDepositerOffsets = [blankFunctionDepositerOffset];
initialExecuteFunctionSignatures = [blankFunctionSig];

GenericHandlerInstance = await GenericHandlerContract.new(
BridgeInstance.address,
initialResourceIDs,
initialContractAddresses,
initialDepositFunctionSignatures,
initialDepositFunctionDepositerOffsets,
initialExecuteFunctionSignatures);

await BridgeInstance.adminSetGenericResource(GenericHandlerInstance.address, resourceID, initialContractAddresses[0], initialDepositFunctionSignatures[0], initialExecuteFunctionSignatures[0]);
await BridgeInstance.adminSetGenericResource(GenericHandlerInstance.address, resourceID, initialContractAddresses[0], initialDepositFunctionSignatures[0], initialDepositFunctionDepositerOffsets[0], initialExecuteFunctionSignatures[0]);

depositData = Helpers.createGenericDepositData('0xdeadbeef');
});
Expand Down
3 changes: 2 additions & 1 deletion test/gasBenchmarks/deployments.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ contract('Gas Benchmark - [contract deployments]', async () => {
const initialContractAddresses = [];
const burnableContractAddresses = [];
const initialDepositFunctionSignatures = [];
const initialDepositFunctionDepositerOffsets = [];
const initialExecuteFunctionSignatures = [];
const centrifugeAssetMinCount = 1;
const gasBenchmarks = [];
Expand All @@ -30,7 +31,7 @@ contract('Gas Benchmark - [contract deployments]', async () => {
await Promise.all([
ERC20HandlerContract.new(BridgeInstance.address, initialResourceIDs, initialContractAddresses, burnableContractAddresses),
ERC721HandlerContract.new(BridgeInstance.address, initialResourceIDs, initialContractAddresses, burnableContractAddresses),
GenericHandlerContract.new(BridgeInstance.address, initialResourceIDs, initialContractAddresses, initialDepositFunctionSignatures, initialExecuteFunctionSignatures),
GenericHandlerContract.new(BridgeInstance.address, initialResourceIDs, initialContractAddresses, initialDepositFunctionSignatures, initialDepositFunctionDepositerOffsets, initialExecuteFunctionSignatures),
CentrifugeAssetContract.new(centrifugeAssetMinCount),
HandlerHelpersContract.new(),
ERC20SafeContract.new(),
Expand Down

0 comments on commit a8a8805

Please sign in to comment.