Skip to content

Commit

Permalink
Add lint CI workflow
Browse files Browse the repository at this point in the history
  • Loading branch information
Benjimmutable committed Oct 24, 2023
1 parent e5b5428 commit c88ad56
Show file tree
Hide file tree
Showing 11 changed files with 99 additions and 70 deletions.
28 changes: 28 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Lint Check

on: [push]

env:
FOUNDRY_PROFILE: ci

jobs:
check:
strategy:
fail-fast: true

name: Forge Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
submodules: recursive

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
with:
version: nightly

- name: Run Forge fmt --check
run: |
forge fmt --check
id: fmt
8 changes: 4 additions & 4 deletions script/InitializeChildContracts.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ contract InitializeChildContracts is Script {
function run() public {
uint256 deployerPrivateKey = vm.envUint("CHILD_PRIVATE_KEY");
ChildERC20Bridge childERC20Bridge = ChildERC20Bridge(vm.envAddress("CHILD_ERC20_BRIDGE"));
ChildAxelarBridgeAdaptor childAxelarBridgeAdaptor = ChildAxelarBridgeAdaptor(vm.envAddress("CHILD_BRIDGE_ADAPTOR"));
ChildAxelarBridgeAdaptor childAxelarBridgeAdaptor =
ChildAxelarBridgeAdaptor(vm.envAddress("CHILD_BRIDGE_ADAPTOR"));
address childTokenTemplate = vm.envAddress("CHILDCHAIN_CHILD_TOKEN_TEMPLATE");
address rootERC20BridgeAdaptor = vm.envAddress("ROOT_BRIDGE_ADAPTOR");
string memory childRpcUrl = vm.envString("CHILD_RPC_URL");
Expand All @@ -27,8 +28,8 @@ contract InitializeChildContracts is Script {
vm.startBroadcast(deployerPrivateKey);

childERC20Bridge.initialize(
address(childAxelarBridgeAdaptor),
Strings.toHexString(rootERC20BridgeAdaptor),
address(childAxelarBridgeAdaptor),
Strings.toHexString(rootERC20BridgeAdaptor),
childTokenTemplate,
rootChainName,
rootIMXToken
Expand All @@ -37,6 +38,5 @@ contract InitializeChildContracts is Script {
childAxelarBridgeAdaptor.setRootBridgeAdaptor();

vm.stopBroadcast();

}
}
2 changes: 1 addition & 1 deletion script/InitializeRootContracts.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ contract InitializeRootContracts is Script {
string memory rootRpcUrl = vm.envString("ROOT_RPC_URL");
uint256 rootPrivateKey = vm.envUint("ROOT_PRIVATE_KEY");
address rootIMXToken = vm.envAddress("ROOT_IMX_ADDRESS");
address childETHToken = vm.envAddress("CHILD_ETH_ADDRESS");
address childETHToken = vm.envAddress("CHILD_ETH_ADDRESS");

/**
* INITIALIZE ROOT CHAIN CONTRACTS
Expand Down
6 changes: 2 additions & 4 deletions src/child/ChildERC20Bridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,7 @@ contract ChildERC20Bridge is
string memory newRootChain,
address newIMXToken
) public initializer {
if (newBridgeAdaptor == address(0)
|| newChildTokenTemplate == address(0)
|| newIMXToken == address(0)) {
if (newBridgeAdaptor == address(0) || newChildTokenTemplate == address(0) || newIMXToken == address(0)) {
revert ZeroAddress();
}

Expand Down Expand Up @@ -165,7 +163,7 @@ contract ChildERC20Bridge is
} else {
Address.sendValue(payable(receiver), amount);
emit IMXDeposit(address(rootToken), sender, receiver, amount);
}
}
}

function updateBridgeAdaptor(address newBridgeAdaptor) external override onlyOwner {
Expand Down
7 changes: 1 addition & 6 deletions src/interfaces/child/IChildERC20Bridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,7 @@ interface IChildERC20BridgeEvents {
address indexed receiver,
uint256 amount
);
event IMXDeposit(
address indexed rootToken,
address depositor,
address indexed receiver,
uint256 amount
);
event IMXDeposit(address indexed rootToken, address depositor, address indexed receiver, uint256 amount);
event NativeDeposit(
address indexed rootToken,
address indexed childToken,
Expand Down
7 changes: 1 addition & 6 deletions src/interfaces/root/IRootERC20Bridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,7 @@ interface IRootERC20BridgeEvents {
address indexed receiver,
uint256 amount
);
event IMXDeposit(
address indexed rootToken,
address depositor,
address indexed receiver,
uint256 amount
);
event IMXDeposit(address indexed rootToken, address depositor, address indexed receiver, uint256 amount);
event NativeDeposit(
address indexed rootToken,
address indexed childToken,
Expand Down
32 changes: 15 additions & 17 deletions src/root/RootERC20Bridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -61,19 +61,15 @@ contract RootERC20Bridge is
address newRootBridgeAdaptor,
address newChildERC20Bridge,
address newChildBridgeAdaptor,
address newChildTokenTemplate,
address newChildTokenTemplate,
address newRootIMXToken,
address newChildETHToken)
public
initializer
{
if (newRootBridgeAdaptor == address(0)
|| newChildERC20Bridge == address(0)
|| newChildTokenTemplate == address(0)
|| newChildBridgeAdaptor == address(0)
|| newRootIMXToken == address(0)
|| newChildETHToken == address(0))
{
address newChildETHToken
) public initializer {
if (
newRootBridgeAdaptor == address(0) || newChildERC20Bridge == address(0)
|| newChildTokenTemplate == address(0) || newChildBridgeAdaptor == address(0)
|| newRootIMXToken == address(0) || newChildETHToken == address(0)
) {
revert ZeroAddress();
}
childERC20Bridge = newChildERC20Bridge;
Expand All @@ -95,11 +91,13 @@ contract RootERC20Bridge is
return _mapToken(rootToken);
}

function depositETH(uint256 amount) external payable { //override removed?
function depositETH(uint256 amount) external payable {
//override removed?
_depositETH(msg.sender, amount);
}

function depositToETH(address receiver, uint256 amount) external payable { //override removed?
function depositToETH(address receiver, uint256 amount) external payable {
//override removed?
_depositETH(receiver, amount);
}

Expand All @@ -109,7 +107,7 @@ contract RootERC20Bridge is
}

uint256 expectedBalance = address(this).balance - (msg.value - amount);

_deposit(IERC20Metadata(NATIVE_TOKEN), receiver, amount);

// invariant check to ensure that the root native balance has increased by the amount deposited
Expand Down Expand Up @@ -186,7 +184,7 @@ contract RootERC20Bridge is
// TODO We can call _mapToken here, but ordering in the GMP is not guaranteed.
// Therefore, we need to decide how to handle this and it may be a UI decision to wait until map token message is executed on child chain.
// Discuss this, and add this decision to the design doc.
if (address(rootToken) != NATIVE_TOKEN) {
if (address(rootToken) != NATIVE_TOKEN) {
if (address(rootToken) != rootIMXToken) {
childToken = rootTokenToChildToken[address(rootToken)];
if (childToken == address(0)) {
Expand All @@ -199,7 +197,7 @@ contract RootERC20Bridge is
} else {
feeAmount = msg.value - amount;
}

// Deposit sig, root token address, depositor, receiver, amount
bytes memory payload = abi.encode(DEPOSIT_SIG, rootToken, msg.sender, receiver, amount);
// TODO investigate using delegatecall to keep the axelar message sender as the bridge contract, since adaptor can change.
Expand Down
3 changes: 2 additions & 1 deletion test/integration/root/RootERC20Bridge.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ contract RootERC20BridgeIntegrationTest is Test, IRootERC20BridgeEvents, IRootAx
function test_depositToken() public {
uint256 tokenAmount = 300;
string memory childBridgeAdaptorString = Strings.toHexString(CHILD_BRIDGE_ADAPTOR);
(address childToken, bytes memory predictedPayload) = setupDeposit(token, rootBridge, mapTokenFee, depositFee, tokenAmount, true);
(address childToken, bytes memory predictedPayload) =
setupDeposit(token, rootBridge, mapTokenFee, depositFee, tokenAmount, true);

vm.expectEmit(address(axelarAdaptor));
emit MapTokenAxelarMessage(CHILD_CHAIN_NAME, childBridgeAdaptorString, predictedPayload);
Expand Down
15 changes: 8 additions & 7 deletions test/unit/child/ChildERC20Bridge.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ contract ChildERC20BridgeUnitTest is Test, IChildERC20BridgeEvents, IChildERC20B

childBridge = new ChildERC20Bridge();

childBridge.initialize(address(this), ROOT_BRIDGE_ADAPTOR, address(childTokenTemplate), ROOT_CHAIN_NAME, IMX_TOKEN);
childBridge.initialize(
address(this), ROOT_BRIDGE_ADAPTOR, address(childTokenTemplate), ROOT_CHAIN_NAME, IMX_TOKEN
);
}

function test_Initialize() public {
Expand All @@ -45,7 +47,9 @@ contract ChildERC20BridgeUnitTest is Test, IChildERC20BridgeEvents, IChildERC20B

function test_RevertIfInitializeTwice() public {
vm.expectRevert("Initializable: contract is already initialized");
childBridge.initialize(address(this), ROOT_BRIDGE_ADAPTOR, address(childTokenTemplate), ROOT_CHAIN_NAME, IMX_TOKEN);
childBridge.initialize(
address(this), ROOT_BRIDGE_ADAPTOR, address(childTokenTemplate), ROOT_CHAIN_NAME, IMX_TOKEN
);
}

function test_RevertIf_InitializeWithAZeroAddressAdapter() public {
Expand Down Expand Up @@ -182,9 +186,7 @@ contract ChildERC20BridgeUnitTest is Test, IChildERC20BridgeEvents, IChildERC20B
}

function test_RevertIf_mapTokenCalledWithIMXAddress() public {
bytes memory data = abi.encode(
childBridge.MAP_TOKEN_SIG(), IMX_TOKEN, "ImmutableX", "IMX", 18
);
bytes memory data = abi.encode(childBridge.MAP_TOKEN_SIG(), IMX_TOKEN, "ImmutableX", "IMX", 18);
vm.expectRevert(CantMapIMX.selector);
childBridge.onMessageReceive(ROOT_CHAIN_NAME, ROOT_BRIDGE_ADAPTOR, data);
}
Expand Down Expand Up @@ -220,7 +222,6 @@ contract ChildERC20BridgeUnitTest is Test, IChildERC20BridgeEvents, IChildERC20B
//Deposit

function test_onMessageReceive_DepositIMX_EmitsIMXDepositEvent() public {

uint256 fundedAmount = 10 ether;
vm.deal(address(childBridge), fundedAmount);

Expand Down Expand Up @@ -251,7 +252,7 @@ contract ChildERC20BridgeUnitTest is Test, IChildERC20BridgeEvents, IChildERC20B
assertEq(receiver.balance, amount, "receiver balance not increased");
}

function test_RevertIf_onMessageReceive_DepositIMX_InsufficientBalance() public {
function test_RevertIf_onMessageReceive_DepositIMX_InsufficientBalance() public {
uint256 fundedAmount = 1 ether;
vm.deal(address(childBridge), fundedAmount);

Expand Down
45 changes: 28 additions & 17 deletions test/unit/root/RootERC20Bridge.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ contract RootERC20BridgeUnitTest is Test, IRootERC20BridgeEvents, IRootERC20Brid
mockAxelarAdaptor = new MockAdaptor();

// The specific ERC20 token template does not matter for these unit tests
rootBridge.initialize(address(mockAxelarAdaptor), CHILD_BRIDGE, CHILD_BRIDGE_ADAPTOR, address(token), IMX_TOKEN, CHILD_ETH_TOKEN);
rootBridge.initialize(
address(mockAxelarAdaptor), CHILD_BRIDGE, CHILD_BRIDGE_ADAPTOR, address(token), IMX_TOKEN, CHILD_ETH_TOKEN
);
}

/**
Expand All @@ -58,7 +60,9 @@ contract RootERC20BridgeUnitTest is Test, IRootERC20BridgeEvents, IRootERC20Brid

function test_RevertIfInitializeTwice() public {
vm.expectRevert("Initializable: contract is already initialized");
rootBridge.initialize(address(mockAxelarAdaptor), CHILD_BRIDGE, CHILD_BRIDGE_ADAPTOR, address(token), IMX_TOKEN, CHILD_ETH_TOKEN);
rootBridge.initialize(
address(mockAxelarAdaptor), CHILD_BRIDGE, CHILD_BRIDGE_ADAPTOR, address(token), IMX_TOKEN, CHILD_ETH_TOKEN
);
}

function test_RevertIf_InitializeWithAZeroAddressRootAdapter() public {
Expand Down Expand Up @@ -118,7 +122,6 @@ contract RootERC20BridgeUnitTest is Test, IRootERC20BridgeEvents, IRootERC20Brid
}

function test_mapToken_CallsAdaptor() public {

bytes memory payload =
abi.encode(rootBridge.MAP_TOKEN_SIG(), token, token.name(), token.symbol(), token.decimals());

Expand Down Expand Up @@ -201,15 +204,16 @@ contract RootERC20BridgeUnitTest is Test, IRootERC20BridgeEvents, IRootERC20Brid

function test_depositETHCallsSendMessage() public {
uint256 amount = 1000;
(, bytes memory predictedPayload) = setupDeposit(ERC20PresetMinterPauser(NATIVE_TOKEN), rootBridge, mapTokenFee, depositFee, amount, false);
(, bytes memory predictedPayload) =
setupDeposit(ERC20PresetMinterPauser(NATIVE_TOKEN), rootBridge, mapTokenFee, depositFee, amount, false);

vm.expectCall(
address(mockAxelarAdaptor),
depositFee,
abi.encodeWithSelector(mockAxelarAdaptor.sendMessage.selector, predictedPayload, address(this))
);

rootBridge.depositETH{value: amount+depositFee}(amount);
rootBridge.depositETH{value: amount + depositFee}(amount);
}

function test_depositETHEmitsNativeDepositEvent() public {
Expand All @@ -218,51 +222,57 @@ contract RootERC20BridgeUnitTest is Test, IRootERC20BridgeEvents, IRootERC20Brid

vm.expectEmit();
emit NativeDeposit(NATIVE_TOKEN, CHILD_ETH_TOKEN, address(this), address(this), amount);
rootBridge.depositETH{value: amount+depositFee}(amount);
rootBridge.depositETH{value: amount + depositFee}(amount);
}

function test_RevertIf_depositETHInsufficientValue() public {
uint256 amount = 1000;
setupDeposit(ERC20PresetMinterPauser(NATIVE_TOKEN), rootBridge, mapTokenFee, depositFee, amount, false);

vm.expectRevert(InsufficientValue.selector);
rootBridge.depositETH{value: (amount/2)+depositFee}(amount);
rootBridge.depositETH{value: (amount / 2) + depositFee}(amount);
}

/**
/**
* DEPOSIT TO ETH
*/

function test_depositToETHCallsSendMessage() public {
uint256 amount = 1000;
address receiver = address(12345);
(, bytes memory predictedPayload) = setupDepositTo(ERC20PresetMinterPauser(NATIVE_TOKEN), rootBridge, mapTokenFee, depositFee, amount, receiver, false);
(, bytes memory predictedPayload) = setupDepositTo(
ERC20PresetMinterPauser(NATIVE_TOKEN), rootBridge, mapTokenFee, depositFee, amount, receiver, false
);
vm.expectCall(
address(mockAxelarAdaptor),
depositFee,
abi.encodeWithSelector(mockAxelarAdaptor.sendMessage.selector, predictedPayload, address(this))
);

rootBridge.depositToETH{value: amount+depositFee}(receiver, amount);
rootBridge.depositToETH{value: amount + depositFee}(receiver, amount);
}

function test_depositToETHEmitsNativeDepositEvent() public {
uint256 amount = 1000;
address receiver = address(12345);
setupDepositTo(ERC20PresetMinterPauser(NATIVE_TOKEN), rootBridge, mapTokenFee, depositFee, amount, receiver, false);
setupDepositTo(
ERC20PresetMinterPauser(NATIVE_TOKEN), rootBridge, mapTokenFee, depositFee, amount, receiver, false
);

vm.expectEmit();
emit NativeDeposit(NATIVE_TOKEN, CHILD_ETH_TOKEN, address(this), receiver, amount);
rootBridge.depositToETH{value: amount+depositFee}(receiver, amount);
rootBridge.depositToETH{value: amount + depositFee}(receiver, amount);
}

function test_RevertIf_depositToETHInsufficientValue() public {
uint256 amount = 1000;
address receiver = address(12345);
setupDepositTo(ERC20PresetMinterPauser(NATIVE_TOKEN), rootBridge, mapTokenFee, depositFee, amount, receiver, false);
setupDepositTo(
ERC20PresetMinterPauser(NATIVE_TOKEN), rootBridge, mapTokenFee, depositFee, amount, receiver, false
);

vm.expectRevert(InsufficientValue.selector);
rootBridge.depositToETH{value: (amount/2)+depositFee}(receiver, amount);
rootBridge.depositToETH{value: (amount / 2) + depositFee}(receiver, amount);
}

/**
Expand All @@ -274,7 +284,7 @@ contract RootERC20BridgeUnitTest is Test, IRootERC20BridgeEvents, IRootERC20Brid
setupDeposit(ERC20PresetMinterPauser(NATIVE_TOKEN), rootBridge, mapTokenFee, depositFee, amount, false);

vm.expectRevert(ZeroAmount.selector);
rootBridge.depositETH{value: amount+depositFee}(amount);
rootBridge.depositETH{value: amount + depositFee}(amount);
}

function test_RevertIf_depositToETHAmountIsZero() public {
Expand All @@ -284,7 +294,7 @@ contract RootERC20BridgeUnitTest is Test, IRootERC20BridgeEvents, IRootERC20Brid
setupDeposit(ERC20PresetMinterPauser(NATIVE_TOKEN), rootBridge, mapTokenFee, depositFee, amount, false);

vm.expectRevert(ZeroAmount.selector);
rootBridge.depositToETH{value: amount+depositFee}(receiver, amount);
rootBridge.depositToETH{value: amount + depositFee}(receiver, amount);
}

function test_RevertIf_depositAmountIsZero() public {
Expand Down Expand Up @@ -406,7 +416,8 @@ contract RootERC20BridgeUnitTest is Test, IRootERC20BridgeEvents, IRootERC20Brid
uint256 amount = 100;
address receiver = address(12345);

(, bytes memory predictedPayload) = setupDepositTo(token, rootBridge, mapTokenFee, depositFee, amount, receiver, true);
(, bytes memory predictedPayload) =
setupDepositTo(token, rootBridge, mapTokenFee, depositFee, amount, receiver, true);

vm.expectCall(
address(mockAxelarAdaptor),
Expand Down
Loading

0 comments on commit c88ad56

Please sign in to comment.