Skip to content
This repository was archived by the owner on May 9, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
518a2d6
Initial commit
dankostiuk Sep 3, 2021
1ad7840
Merge branch 'release/v1.0.0'
dankostiuk Sep 3, 2021
d83d72f
update readme
dankostiuk Sep 3, 2021
23cfe82
indexing proposalExecution event
dankostiuk Sep 3, 2021
e2dcda8
adjusted fields on bridge's ProposalExecution event
dankostiuk Sep 7, 2021
a390061
pass in deconstructed fields to ProposalExecution event
dankostiuk Sep 7, 2021
1c817be
moved ERC20ProposalExecuted to ERC20Handler
dankostiuk Sep 7, 2021
c498d12
added graph files
dankostiuk Oct 16, 2021
3385e5f
added commands to deploy to temp graph url
dankostiuk Oct 19, 2021
0bc7689
update to more recent startBlock
dankostiuk Oct 19, 2021
0c1aa45
updated erc20handler contract entity
dankostiuk Oct 20, 2021
6b0232e
fix timestamp field for subgraph schema
dankostiuk Oct 20, 2021
57756e0
update graph url + subgraph config
dankostiuk Oct 22, 2021
6466ad5
deploying to toronto
dankostiuk Nov 24, 2021
5b29e60
add extra fields to support pending transfer events
dankostiuk Dec 15, 2021
443be43
remove direction
dankostiuk Dec 15, 2021
1d292fa
updated contract address
dankostiuk Dec 15, 2021
097a603
add SXVault.sol and tasks
dankostiuk Jan 25, 2022
3989ce2
Test removing requirement of datahash in executeProposal
dankostiuk Jan 26, 2022
7d5879f
Added ERC20SXHandler to deal with native sx
dankostiuk Jan 26, 2022
c1598dc
update contract name for erc20SXHandler
dankostiuk Jan 26, 2022
a66ac7d
calling SXVault contract using interface
dankostiuk Jan 26, 2022
4c404a9
remove comment
dankostiuk Jan 26, 2022
6d5e418
remove comments
dankostiuk Jan 26, 2022
3e5fdd3
additional changes
dankostiuk Jan 27, 2022
19d7c48
added tasks and updating ipfs url
dankostiuk Feb 8, 2022
8027491
updated graph ipfs url again
dankostiuk Feb 8, 2022
2d277cb
Now can burn erc20 tokens that don't implement burnFrom
dankostiuk Feb 16, 2022
2b21a57
Prevent SX deposits out of SXN
dankostiuk Feb 22, 2022
78207d4
use erc20safe.lockerc20 to call safeTransferFrom
dankostiuk Feb 22, 2022
1c42b1e
Apply formatting for better readability + invoke manualBurnERC20 inst…
dankostiuk Mar 3, 2022
8654f56
Include formatting on remaining sol files
dankostiuk Mar 3, 2022
083bae9
Further formatting changes
dankostiuk Mar 3, 2022
34316a7
remove fundERC20 function, add SPDX license identifiers
dankostiuk Mar 8, 2022
3978b43
add husky
akshar Mar 8, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 0 additions & 17 deletions .github/pull_request_template.md

This file was deleted.

3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
.env
.idea/
/build
/artifacts
/cache
.history/
node_modules/
gethdata/
Expand Down
4 changes: 4 additions & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npx lint-staged
8 changes: 8 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
build/
artifacts/
cache/
.history/
node_modules/
gethdata/
gethdata2/
coverage/
15 changes: 15 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"overrides": [
{
"files": "*.sol",
"options": {
"printWidth": 150,
"tabWidth": 4,
"useTabs": false,
"singleQuote": false,
"bracketSpacing": false,
"explicitTypes": "always"
}
}
]
}
12 changes: 10 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# chainbridge-solidity

## SX Network Info

This repo is based off `v1.0.0` of upstream repo https://github.com/ChainSafe/chainbridge-solidity.git.

It is referenced by https://gitlab.com/nextgenbt/sx-network/chainbridge-deploy which maintains our version of the cb-sol-cli tool.

Updates to ChainBridge-related contracts should be merged into the `master` branch here prior to cloning/pulling from the repo above.

## ChainBridge

[![Coverage Status](https://coveralls.io/repos/github/ChainSafe/chainbridge-solidity/badge.svg?branch=master)](https://coveralls.io/github/ChainSafe/chainbridge-solidity?branch=master)

ChainBridge uses Solidity smart contracts to enable transfers to and from EVM compatible chains. These contracts consist of a core bridge contract (Bridge.sol) and a set of handler contracts (ERC20Handler.sol, ERC721Handler.sol, and GenericHandler.sol). The bridge contract is responsible for initiating, voting on, and executing proposed transfers. The handlers are used by the bridge contract to interact with other existing contracts.
Expand Down Expand Up @@ -29,5 +39,3 @@ Requires `nodejs` and `npm`.
`make test`: Runs truffle tests.

`make compile`: Compile contracts.


123 changes: 73 additions & 50 deletions contracts/Bridge.sol
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity 0.6.4;
pragma experimental ABIEncoderV2;

Expand All @@ -14,17 +15,25 @@ import "./interfaces/IGenericHandler.sol";
@author ChainSafe Systems.
*/
contract Bridge is Pausable, AccessControl, SafeMath {

uint8 public _chainID;
uint8 public _chainID;
uint256 public _relayerThreshold;
uint256 public _totalRelayers;
uint256 public _totalProposals;
uint256 public _fee;
uint256 public _expiry;

enum Vote {No, Yes}
enum Vote {
No,
Yes
}

enum ProposalStatus {Inactive, Active, Passed, Executed, Cancelled}
enum ProposalStatus {
Inactive,
Active,
Passed,
Executed,
Cancelled
}

struct Proposal {
bytes32 _resourceID;
Expand All @@ -46,28 +55,19 @@ 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(
uint8 indexed destinationChainID,
bytes32 indexed resourceID,
uint64 indexed depositNonce
);
event Deposit(uint8 indexed destinationChainID, bytes32 indexed resourceID, uint64 indexed depositNonce);
event ProposalEvent(
uint8 indexed originChainID,
uint64 indexed depositNonce,
ProposalStatus indexed status,
uint8 indexed originChainID,
uint64 indexed depositNonce,
ProposalStatus indexed status,
bytes32 resourceID,
bytes32 dataHash
);

event ProposalVote(
uint8 indexed originChainID,
uint64 indexed depositNonce,
ProposalStatus indexed status,
bytes32 resourceID
);
event ProposalVote(uint8 indexed originChainID, uint64 indexed depositNonce, ProposalStatus indexed status, bytes32 resourceID);

bytes32 public constant RELAYER_ROLE = keccak256("RELAYER_ROLE");

Expand All @@ -87,8 +87,7 @@ contract Bridge is Pausable, AccessControl, SafeMath {
}

function _onlyAdminOrRelayer() private {
require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender) || hasRole(RELAYER_ROLE, msg.sender),
"sender is not relayer or admin");
require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender) || hasRole(RELAYER_ROLE, msg.sender), "sender is not relayer or admin");
}

function _onlyAdmin() private {
Expand All @@ -106,7 +105,13 @@ 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;
Expand All @@ -115,11 +120,10 @@ contract Bridge is Pausable, AccessControl, SafeMath {
_setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
_setRoleAdmin(RELAYER_ROLE, DEFAULT_ADMIN_ROLE);

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

}

/**
Expand Down Expand Up @@ -162,7 +166,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 @@ -201,7 +205,11 @@ contract Bridge is Pausable, AccessControl, SafeMath {
@param resourceID ResourceID to be used when making deposits.
@param tokenAddress Address of contract to be called when a deposit is made and a deposited is executed.
*/
function adminSetResource(address handlerAddress, bytes32 resourceID, address tokenAddress) external onlyAdmin {
function adminSetResource(
address handlerAddress,
bytes32 resourceID,
address tokenAddress
) external onlyAdmin {
_resourceIDToHandlerAddress[resourceID] = handlerAddress;
IERCHandler handler = IERCHandler(handlerAddress);
handler.setResource(resourceID, tokenAddress);
Expand Down Expand Up @@ -249,7 +257,11 @@ contract Bridge is Pausable, AccessControl, SafeMath {
- _noVotes Number of votes against proposal.
- _status Current status of proposal.
*/
function getProposal(uint8 originChainID, uint64 depositNonce, bytes32 dataHash) external view returns (Proposal memory) {
function getProposal(
uint8 originChainID,
uint64 depositNonce,
bytes32 dataHash
) external view returns (Proposal memory) {
uint72 nonceAndID = (uint72(depositNonce) << 8) | uint72(originChainID);
return _proposals[nonceAndID][dataHash];
}
Expand All @@ -259,7 +271,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 @@ -289,7 +301,11 @@ contract Bridge is Pausable, AccessControl, SafeMath {
@param data Additional data to be passed to specified handler.
@notice Emits {Deposit} event.
*/
function deposit(uint8 destinationChainID, bytes32 resourceID, bytes calldata data) external payable whenNotPaused {
function deposit(
uint8 destinationChainID,
bytes32 resourceID,
bytes calldata data
) external payable whenNotPaused {
require(msg.value == _fee, "Incorrect fee supplied");

address handler = _resourceIDToHandlerAddress[resourceID];
Expand All @@ -315,25 +331,29 @@ contract Bridge is Pausable, AccessControl, SafeMath {
@notice Emits {ProposalEvent} event with status indicating the proposal status.
@notice Emits {ProposalVote} event.
*/
function voteProposal(uint8 chainID, uint64 depositNonce, bytes32 resourceID, bytes32 dataHash) external onlyRelayers whenNotPaused {

function voteProposal(
uint8 chainID,
uint64 depositNonce,
bytes32 resourceID,
bytes32 dataHash
) external onlyRelayers whenNotPaused {
uint72 nonceAndID = (uint72(depositNonce) << 8) | uint72(chainID);
Proposal storage proposal = _proposals[nonceAndID][dataHash];

require(_resourceIDToHandlerAddress[resourceID] != address(0), "no handler for resourceID");
require(uint(proposal._status) <= 1, "proposal already passed/executed/cancelled");
require(uint256(proposal._status) <= 1, "proposal already passed/executed/cancelled");
require(!_hasVotedOnProposal[nonceAndID][dataHash][msg.sender], "relayer already voted");

if (uint(proposal._status) == 0) {
if (uint256(proposal._status) == 0) {
++_totalProposals;
_proposals[nonceAndID][dataHash] = Proposal({
_resourceID : resourceID,
_dataHash : dataHash,
_yesVotes : new address[](1),
_noVotes : new address[](0),
_status : ProposalStatus.Active,
_proposedBlock : block.number
});
_resourceID: resourceID,
_dataHash: dataHash,
_yesVotes: new address[](1),
_noVotes: new address[](0),
_status: ProposalStatus.Active,
_proposedBlock: block.number
});

proposal._yesVotes[0] = msg.sender;
emit ProposalEvent(chainID, depositNonce, ProposalStatus.Active, resourceID, dataHash);
Expand All @@ -346,10 +366,7 @@ contract Bridge is Pausable, AccessControl, SafeMath {
} else {
require(dataHash == proposal._dataHash, "datahash mismatch");
proposal._yesVotes.push(msg.sender);


}

}
if (proposal._status != ProposalStatus.Cancelled) {
_hasVotedOnProposal[nonceAndID][dataHash][msg.sender] = true;
Expand All @@ -363,7 +380,6 @@ contract Bridge is Pausable, AccessControl, SafeMath {
emit ProposalEvent(chainID, depositNonce, ProposalStatus.Passed, resourceID, dataHash);
}
}

}

/**
Expand All @@ -375,7 +391,11 @@ contract Bridge is Pausable, AccessControl, SafeMath {
@notice Proposal must be past expiry threshold.
@notice Emits {ProposalEvent} event with status {Cancelled}.
*/
function cancelProposal(uint8 chainID, uint64 depositNonce, bytes32 dataHash) public onlyAdminOrRelayer {
function cancelProposal(
uint8 chainID,
uint64 depositNonce,
bytes32 dataHash
) public onlyAdminOrRelayer {
uint72 nonceAndID = (uint72(depositNonce) << 8) | uint72(chainID);
Proposal storage proposal = _proposals[nonceAndID][dataHash];

Expand All @@ -384,7 +404,6 @@ contract Bridge is Pausable, AccessControl, SafeMath {

proposal._status = ProposalStatus.Cancelled;
emit ProposalEvent(chainID, depositNonce, ProposalStatus.Cancelled, proposal._resourceID, proposal._dataHash);

}

/**
Expand All @@ -398,7 +417,12 @@ contract Bridge is Pausable, AccessControl, SafeMath {
@notice Hash of {data} must equal proposal's {dataHash}.
@notice Emits {ProposalEvent} event with status {Executed}.
*/
function executeProposal(uint8 chainID, uint64 depositNonce, bytes calldata data, bytes32 resourceID) external onlyRelayers whenNotPaused {
function executeProposal(
uint8 chainID,
uint64 depositNonce,
bytes calldata data,
bytes32 resourceID
) external onlyRelayers whenNotPaused {
address handler = _resourceIDToHandlerAddress[resourceID];
uint72 nonceAndID = (uint72(depositNonce) << 8) | uint72(chainID);
bytes32 dataHash = keccak256(abi.encodePacked(handler, data));
Expand All @@ -422,10 +446,9 @@ contract Bridge is Pausable, AccessControl, SafeMath {
@param addrs Array of addresses to transfer {amounts} to.
@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++) {
function transferFunds(address payable[] calldata addrs, uint256[] calldata amounts) external onlyAdmin {
for (uint256 i = 0; i < addrs.length; i++) {
addrs[i].transfer(amounts[i]);
}
}

}
18 changes: 9 additions & 9 deletions contracts/CentrifugeAsset.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,20 @@ pragma experimental ABIEncoderV2;
@author ChainSafe Systems.
*/
contract CentrifugeAsset {
mapping (bytes32 => bool) public _assetsStored;
mapping(bytes32 => bool) public _assetsStored;

event AssetStored(bytes32 indexed asset);
event AssetStored(bytes32 indexed asset);

/**
/**
@notice Marks {asset} as stored.
@param asset Hash of asset deposited on Centrifuge chain.
@notice {asset} must not have already been stored.
@notice Emits {AssetStored} event.
*/
function store(bytes32 asset) external {
require(!_assetsStored[asset], "asset is already stored");
function store(bytes32 asset) external {
require(!_assetsStored[asset], "asset is already stored");

_assetsStored[asset] = true;
emit AssetStored(asset);
}
}
_assetsStored[asset] = true;
emit AssetStored(asset);
}
}
Loading