Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Contracts V3 #882

Merged
merged 47 commits into from
Jul 30, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
f27654c
first commit
vgeddes Jul 2, 2023
c2b230e
foo
vgeddes Jul 13, 2023
7f6f8ff
add more tests
vgeddes Jul 15, 2023
77c2c54
fix solhint
vgeddes Jul 15, 2023
e3ceb3a
Merge branch 'main' into proxy-contracts
vgeddes Jul 16, 2023
68473a7
fix merge conflict
vgeddes Jul 16, 2023
f06691c
Improve contracts
vgeddes Jul 17, 2023
6d44b0d
More improvements to contracts
vgeddes Jul 18, 2023
669d414
Fix parachain build in proxy-contracts branch (#889)
doubledup Jul 19, 2023
d815bf4
add more unit test coverage
vgeddes Jul 19, 2023
2a9f2b0
Improve mmr proof test
vgeddes Jul 19, 2023
d053333
rename contract
vgeddes Jul 19, 2023
b0fe1b8
forge install: openzeppelin-contracts
vgeddes Jul 19, 2023
a9df610
fix gitmodules
vgeddes Jul 19, 2023
f89d7b9
sno-472 rebased (#890)
yrong Jul 20, 2023
bce2a2c
Update cumulus
yrong Jul 20, 2023
7888b50
Merge branch 'main' into proxy-contracts
yrong Jul 20, 2023
d376fcc
Fix test
yrong Jul 20, 2023
d43b5ad
Proxy contracts Tests fixes (#892)
alistair-singh Jul 20, 2023
d44ec59
Revert rustfmt (#896)
alistair-singh Jul 20, 2023
4ca8d80
SNO-565: Make parachain relayers use Gateway contract (#888)
doubledup Jul 20, 2023
8350a9a
Update .gitmodules
vgeddes Jul 20, 2023
7b7a037
Create agent (#895)
alistair-singh Jul 20, 2023
a976f30
Update parachain for latest changes in contracts
vgeddes Jul 20, 2023
1c06d27
Move beefy initialize params to construct (#893)
yrong Jul 21, 2023
4f9d563
SNO-566: Execution relayer watching for gateway messages (#897)
doubledup Jul 23, 2023
3c1e87a
improve API for sending tokens
vgeddes Jul 23, 2023
23ec37c
Create Agent (#899)
alistair-singh Jul 23, 2023
978e201
update cumulus
vgeddes Jul 23, 2023
9700fc5
improve pallets
vgeddes Jul 23, 2023
5f14f5f
Update cumulus: add set_gateway to safe call filter
doubledup Jul 24, 2023
6302ee6
Update cumulus.
Jul 25, 2023
2ba5dba
Update bindings in smoketests
vgeddes Jul 25, 2023
50ea024
Fix golang nonsense
vgeddes Jul 25, 2023
a2c96f8
Handle customized error (#900)
yrong Jul 25, 2023
3627bb6
fix gopath
alistair-singh Jul 25, 2023
a6d19c9
fix unbound vars error in scripts
alistair-singh Jul 25, 2023
eaa9eee
Update inbound queue benchmarks. (#902)
claravanstaden Jul 26, 2023
686135a
remove duplicate openzeppelin submodule
vgeddes Jul 26, 2023
d425a58
Improve beefy tests (#901)
yrong Jul 27, 2023
996469a
Fix execution relay (#905)
yrong Jul 27, 2023
c9c98ef
SNO-517: Check validator set size in submitFinal (#903)
doubledup Jul 28, 2023
b0f922c
Asset transfer (#904)
alistair-singh Jul 28, 2023
d471559
Add more documentation in contracts (#908)
vgeddes Jul 28, 2023
4cff185
Merge branch 'main' into proxy-contracts
vgeddes Jul 28, 2023
0bdac07
Move contracts to repo root directory (#909)
yrong Jul 29, 2023
2019277
more tweaks to dev env
vgeddes Jul 30, 2023
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
2 changes: 1 addition & 1 deletion .husky/pre-commit
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ set -e
echo 'Running pre-commit hook...'

# check typos
chronic typos .
#chronic typos .

# lint and format for core contracts and typescript codes
(cd core && chronic pnpm lint && pnpm format)
Expand Down
6 changes: 5 additions & 1 deletion core/packages/contracts/.solhint.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@
"rules": {
"compiler-version": ["error", "0.8.20"],
"func-visibility": ["warn", {"ignoreConstructors":true}],
"private-vars-leading-underscore": ["off",{"strict":false}],
"not-rely-on-time": "off",
"avoid-low-level-calls": "off",
"no-inline-assembly": "off"
"no-inline-assembly": "off",
"no-empty-blocks": "off",
"func-name-mixedcase": "off",
"no-console": "off"
}
}
54 changes: 54 additions & 0 deletions core/packages/contracts/src/Agent.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2023 Snowfork <hello@snowfork.com>
pragma solidity 0.8.20;

contract Agent {
error Unauthorized();
error InsufficientBalance();
error WithdrawFailed();
error InvokeFailed();

// The unique ID for this agent, derived from the MultiLocation of the corresponding consensus system on Polkadot
bytes32 public immutable agentID;

// The gateway contract owning this agent
address public immutable gateway;

modifier onlyGateway() {
if (msg.sender != gateway) {
revert Unauthorized();
}
_;
}

constructor(bytes32 _agentID) {
agentID = _agentID;
gateway = msg.sender;
}

receive() external payable {}

function withdrawTo(address payable recipient, uint256 amount) external onlyGateway {
if (amount == 0) {
return;
}

if (address(this).balance < amount) {
revert InsufficientBalance();
}

(bool success,) = recipient.call{value: amount}("");
if (!success) {
revert WithdrawFailed();
}
}

function invoke(address delegate, bytes calldata data) external onlyGateway returns (bytes memory) {
(bool success, bytes memory result) = delegate.delegatecall(data);
if (!success) {
revert InvokeFailed();
}

return result;
}
}
50 changes: 50 additions & 0 deletions core/packages/contracts/src/AgentExecutor.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2023 Snowfork <hello@snowfork.com>
pragma solidity 0.8.20;

import {AccessControl} from "openzeppelin/access/AccessControl.sol";
import {ParaID} from "./Types.sol";
import {SubstrateTypes} from "./SubstrateTypes.sol";

import {IGateway} from "./IGateway.sol";

import {IERC20Metadata} from "openzeppelin/token/ERC20/extensions/IERC20Metadata.sol";
import {IERC20} from "openzeppelin/token/ERC20/IERC20.sol";
import {SafeERC20} from "openzeppelin/token/ERC20/utils/SafeERC20.sol";

import {console} from "forge-std/console.sol";

contract AgentExecutor {
using SafeERC20 for IERC20;

bytes32 public constant ACTION_UNLOCK_TOKENS = keccak256("unlockTokens");

event NativeTokensUnlocked(address token, address recipient, uint256 amount);

error InsufficientBalance();
error TransferEthFailed();
error Unauthorized();

function execute(address, bytes memory data) external {
yrong marked this conversation as resolved.
Show resolved Hide resolved
(bytes32 action, bytes memory actionData) = abi.decode(data, (bytes32, bytes));
if (action == ACTION_UNLOCK_TOKENS) {
unlockNativeTokens(actionData);
}
}

function unlockNativeTokens(bytes memory data) internal {
(address token, address recipient, uint256 amount) = abi.decode(data, (address, address, uint256));
IERC20(token).safeTransfer(recipient, amount);
emit NativeTokensUnlocked(token, recipient, amount);
}

function withdrawTo(address payable recipient, uint256 amount) external {
if (address(this).balance < amount) {
revert InsufficientBalance();
}
(bool success,) = recipient.call{value: amount}("");
if (!success) {
revert TransferEthFailed();
}
}
}
14 changes: 0 additions & 14 deletions core/packages/contracts/src/Auth.sol

This file was deleted.

160 changes: 52 additions & 108 deletions core/packages/contracts/src/DeployScript.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,133 +4,77 @@ pragma solidity 0.8.20;

import {WETH9} from "canonical-weth/WETH9.sol";
import {Script} from "forge-std/Script.sol";
import {BeefyClient} from "../src/BeefyClient.sol";
import {ParachainClient} from "../src/ParachainClient.sol";
import {InboundQueue} from "../src/InboundQueue.sol";
import {IRecipient} from "../src/IRecipient.sol";
import {OutboundQueue} from "../src/OutboundQueue.sol";
import {NativeTokens} from "../src/NativeTokens.sol";
import {TokenVault} from "../src/TokenVault.sol";
import {Vault} from "../src/Vault.sol";
import {UpgradeProxy} from "../src/UpgradeProxy.sol";
import {SovereignTreasury} from "../src/SovereignTreasury.sol";
import {Registry} from "../src/Registry.sol";
import {ParaID} from "../src/Types.sol";
import {BeefyClient} from "./BeefyClient.sol";

contract DeployScript is Script {
Registry public registry;
Vault public vault;
BeefyClient public beefyClient;
ParachainClient public parachainClient;
InboundQueue public inboundQueue;
OutboundQueue public outboundQueue;
TokenVault public tokenVault;
NativeTokens public nativeTokens;
UpgradeProxy public upgradeProxy;
import {IGateway} from "./IGateway.sol";
import {GatewayProxy} from "./GatewayProxy.sol";
import {Gateway} from "./Gateway.sol";
import {Agent} from "./Agent.sol";
import {AgentExecutor} from "./AgentExecutor.sol";
import {Features} from "./Features.sol";
import {Verification} from "./Verification.sol";
import {ParaID} from "./Types.sol";

contract DeployScript is Script {
function setUp() public {}

function run() public {
uint256 privateKey = vm.envUint("PRIVATE_KEY");
address deployer = vm.rememberKey(privateKey);
vm.startBroadcast(deployer);

// Registry
registry = new Registry();
registry.grantRole(registry.REGISTER_ROLE(), deployer);

// Vault
vault = new Vault();

// SovereignTreasury
SovereignTreasury treasury = new SovereignTreasury(registry, vault);
registry.registerContract(keccak256("SovereignTreasury"), address(treasury));

// BeefyClient
uint256 randaoCommitDelay = vm.envUint("RANDAO_COMMIT_DELAY");
uint256 randaoCommitExpiration = vm.envUint("RANDAO_COMMIT_EXP");
beefyClient = new BeefyClient(randaoCommitDelay, randaoCommitExpiration);

// ParachainClient
uint32 paraId = uint32(vm.envUint("BRIDGE_HUB_PARAID"));
parachainClient = new ParachainClient(beefyClient, paraId);

// InboundQueue
uint256 relayerReward = vm.envUint("RELAYER_REWARD");
inboundQueue = new InboundQueue(registry, parachainClient, vault, relayerReward);
registry.registerContract(keccak256("InboundQueue"), address(inboundQueue));

// OutboundQueue
uint256 relayerFee = vm.envUint("RELAYER_FEE");
outboundQueue = new OutboundQueue(registry, vault, relayerFee);
registry.registerContract(keccak256("OutboundQueue"), address(outboundQueue));

// NativeTokens
tokenVault = new TokenVault();
nativeTokens = new NativeTokens(
registry,
tokenVault,
ParaID.wrap(uint32(vm.envUint("ASSET_HUB_PARAID"))),
vm.envUint("CREATE_TOKEN_FEE"),
bytes2(vm.envBytes("CREATE_CALL_INDEX")),
bytes2(vm.envBytes("SET_METADATA_CALL_INDEX"))
);
registry.registerContract(keccak256("NativeTokens"), address(nativeTokens));
BeefyClient beefyClient = new BeefyClient(randaoCommitDelay, randaoCommitExpiration);

// Agent Executor
AgentExecutor executor = new AgentExecutor();

Gateway.InitParams memory initParams = Gateway.InitParams({
agentExecutor: address(executor),
fee: vm.envUint("RELAYER_FEE"),
reward: vm.envUint("RELAYER_REWARD"),
bridgeHubParaID: ParaID.wrap(uint32(vm.envUint("BRIDGE_HUB_PARAID"))),
bridgeHubAgentID: keccak256("bridgeHub"),
assetHubParaID: ParaID.wrap(uint32(vm.envUint("ASSET_HUB_PARAID"))),
assetHubAgentID: keccak256("assetHub"),
gasToForward: vm.envUint("GAS_TO_FORWARD"),
features: Features.InitParams({
assetHubParaID: ParaID.wrap(uint32(vm.envUint("ASSET_HUB_PARAID"))),
createTokenFee: vm.envUint("CREATE_TOKEN_FEE"),
createTokenCallId: bytes2(vm.envBytes("CREATE_CALL_INDEX"))
}),
verification: Verification.InitParams({
beefyClient: address(beefyClient),
parachainID: uint32(vm.envUint("BRIDGE_HUB_PARAID"))
})
});

Gateway gatewayLogic = new Gateway();
//gatewayLogic.initialize(initParams);

GatewayProxy gateway = new GatewayProxy(address(gatewayLogic), hex"");
yrong marked this conversation as resolved.
Show resolved Hide resolved

// Deploy WETH for testing
new WETH9();

// UpgradeProxy
upgradeProxy = new UpgradeProxy(registry, ParaID.wrap(paraId));
registry.registerContract(keccak256("UpgradeProxy"), address(upgradeProxy));

// Allow inbound queue to send messages to handlers
nativeTokens.grantRole(nativeTokens.SENDER_ROLE(), address(inboundQueue));
treasury.grantRole(treasury.SENDER_ROLE(), address(inboundQueue));
upgradeProxy.grantRole(upgradeProxy.SENDER_ROLE(), address(inboundQueue));

// Allow handlers to send messages to outbound queue
outboundQueue.grantRole(outboundQueue.SUBMIT_ROLE(), address(nativeTokens));
outboundQueue.grantRole(outboundQueue.SUBMIT_ROLE(), address(treasury));
outboundQueue.grantRole(outboundQueue.SUBMIT_ROLE(), address(upgradeProxy));

// Allow InboundQueue and SovereignTreasury to withdraw from vault
vault.grantRole(vault.WITHDRAW_ROLE(), address(inboundQueue));
vault.grantRole(vault.WITHDRAW_ROLE(), address(treasury));

// Allow NativeTokens to use TokenVault
tokenVault.grantRole(tokenVault.WITHDRAW_ROLE(), address(nativeTokens));
tokenVault.grantRole(tokenVault.DEPOSIT_ROLE(), address(nativeTokens));

// Move ownership of everything to Upgrades app

treasury.grantRole(treasury.ADMIN_ROLE(), address(upgradeProxy));
treasury.revokeRole(treasury.ADMIN_ROLE(), deployer);

nativeTokens.grantRole(nativeTokens.ADMIN_ROLE(), address(upgradeProxy));
nativeTokens.revokeRole(nativeTokens.ADMIN_ROLE(), deployer);

vault.grantRole(vault.ADMIN_ROLE(), address(upgradeProxy));
vault.revokeRole(vault.ADMIN_ROLE(), deployer);

tokenVault.grantRole(tokenVault.ADMIN_ROLE(), address(upgradeProxy));
tokenVault.revokeRole(tokenVault.ADMIN_ROLE(), deployer);

inboundQueue.grantRole(inboundQueue.ADMIN_ROLE(), address(upgradeProxy));
inboundQueue.revokeRole(inboundQueue.ADMIN_ROLE(), deployer);

outboundQueue.grantRole(outboundQueue.ADMIN_ROLE(), address(upgradeProxy));
outboundQueue.revokeRole(outboundQueue.ADMIN_ROLE(), deployer);

registry.grantRole(outboundQueue.ADMIN_ROLE(), address(upgradeProxy));
registry.revokeRole(outboundQueue.ADMIN_ROLE(), deployer);

upgradeProxy.revokeRole(upgradeProxy.ADMIN_ROLE(), deployer);

// Fund the sovereign account for the BridgeHub parachain. Used to reward relayers
// of messages originating from BridgeHub
uint256 initialDeposit = vm.envUint("BRIDGE_HUB_INITIAL_DEPOSIT");
vault.deposit{value: initialDeposit}(ParaID.wrap(paraId));

address bridgeHubAgent = IGateway(address(gateway)).agentOf(initParams.bridgeHubAgentID);
address assetHubAgent = IGateway(address(gateway)).agentOf(initParams.assetHubAgentID);

(bool success,) = bridgeHubAgent.call{value: initialDeposit}("");
if (!success) {
revert("failed to deposit");
}

(success,) = assetHubAgent.call{value: initialDeposit}("");
if (!success) {
revert("failed to deposit");
}

vm.stopBroadcast();
}
Expand Down
Loading
Loading