Skip to content

Commit

Permalink
feat: add full test coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
QEDK committed Jan 13, 2024
1 parent c7a5bfd commit d431c28
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 13 deletions.
2 changes: 1 addition & 1 deletion foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ optimizer_runs = 999999
via_ir = true

[profile.intense.fuzz]
runs = 10000
max_test_rejects = 999999
runs = 10000

[rpc_endpoints]
sepolia = "https://ethereum-sepolia.publicnode.com"
Expand Down
2 changes: 1 addition & 1 deletion script/Deploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ contract GetProofMockScript is Script {
AvailBridge bridge = AvailBridge(address(new TransparentUpgradeableProxy(impl, address(proxyAdmin), "")));
WrappedAvail avail = new WrappedAvail(address(bridge));
bridge.initialize(
IWrappedAvail(address(avail)), admin, admin, IVectorx(0x5ac10644a873AAcd288775A90d6D0303496A4304)
1000000000000, IWrappedAvail(address(avail)), admin, admin, IVectorx(0x5ac10644a873AAcd288775A90d6D0303496A4304)
);
vm.stopBroadcast();
}
Expand Down
2 changes: 1 addition & 1 deletion script/GetProofMockScript.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ contract GetProofMockScript is Script {
address impl = address(new AvailBridge());
AvailBridge bridge = AvailBridge(address(new TransparentUpgradeableProxy(impl, address(admin), "")));
ERC20Mock avail = new ERC20Mock();
bridge.initialize(IWrappedAvail(address(avail)), msg.sender, msg.sender, IVectorx(vectorx));
bridge.initialize(1000000000000, IWrappedAvail(address(avail)), msg.sender, msg.sender, IVectorx(vectorx));
avail.mint(msg.sender, 1 ether);
bridge.sendAVL(bytes32(uint256(1)), 1 ether);
vm.stopBroadcast();
Expand Down
26 changes: 20 additions & 6 deletions src/AvailBridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ contract AvailBridge is
IVectorx public vectorx;
IWrappedAvail public avail;
uint256 public messageId;
uint256 public feePerByte = 10000000000000;
uint256 public feePerByte;

// map store spent message hashes, used for Avail -> Ethereum messages
mapping(bytes32 => bool) public isBridged;
Expand All @@ -95,7 +95,7 @@ contract AvailBridge is
error BridgeRootEmpty();
error DataRootCommitmentEmpty();
error ExceedsMaxDataLength();
error FeeOutsideRange();
error FeeTooLow();
error InvalidAssetId();
error InvalidDataRootProof();
error InvalidDomain();
Expand Down Expand Up @@ -134,10 +134,11 @@ contract AvailBridge is
* @param pauser Address of the pauser multisig
* @param newVectorx Address of the VectorX contract
*/
function initialize(IWrappedAvail newAvail, address governance, address pauser, IVectorx newVectorx)
function initialize(uint256 newFeePerByte, IWrappedAvail newAvail, address governance, address pauser, IVectorx newVectorx)
external
initializer
{
feePerByte = newFeePerByte;
vectorx = newVectorx;
avail = newAvail;
__AccessControlDefaultAdminRules_init(0, governance);
Expand Down Expand Up @@ -187,6 +188,15 @@ contract AvailBridge is
}
}

/**
* @notice Function to update the fee per byte value
* @dev Only callable by governance
* @param newFeePerByte New fee per byte value
*/
function updateFeePerByte(uint256 newFeePerByte) external onlyRole(DEFAULT_ADMIN_ROLE) {
feePerByte = newFeePerByte;
}

/**
* @notice Takes an arbitrary message and its proof of inclusion, verifies and executes it (if valid)
* @dev This function is used for passing arbitrary data from Avail to Ethereum
Expand Down Expand Up @@ -311,9 +321,9 @@ contract AvailBridge is
if (length >= MAX_DATA_LENGTH) {
revert ExceedsMaxDataLength();
}
// ensure that fee is within range
if (msg.value < (length * feePerByte) || msg.value > (4 * length * feePerByte)) {
revert FeeOutsideRange();
// ensure that fee is above minimum amount
if (msg.value < getFee(length)) {
revert FeeTooLow();
}
uint256 id;
unchecked {
Expand Down Expand Up @@ -456,6 +466,10 @@ contract AvailBridge is
return input.leafProof.verify(input.bridgeRoot, input.leafIndex, input.leaf);
}

function getFee(uint256 length) public view returns (uint256) {
return length * feePerByte;
}

/**
* @notice Takes a message and its proof of inclusion, verifies and marks it as spent (if valid)
* @dev This function is used for verifying a message and marking it as spent (if valid)
Expand Down
51 changes: 47 additions & 4 deletions test/AvailBridgeTest.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {VectorxMock, IVectorx} from "src/mocks/VectorxMock.sol";
import {ERC20Mock} from "src/mocks/ERC20Mock.sol";
import {MessageReceiverMock} from "src/mocks/MessageReceiverMock.sol";
import {MurkyBase} from "lib/murky/src/common/MurkyBase.sol";
import {Vm, Test} from "forge-std/Test.sol";
import {Vm, Test, console} from "forge-std/Test.sol";

contract AvailBridgeTest is Test, MurkyBase {
AvailBridge public bridge;
Expand All @@ -29,13 +29,19 @@ contract AvailBridgeTest is Test, MurkyBase {
address impl = address(new AvailBridge());
bridge = AvailBridge(address(new TransparentUpgradeableProxy(impl, address(admin), "")));
avail = new WrappedAvail(address(bridge));
bridge.initialize(IWrappedAvail(address(avail)), msg.sender, pauser, IVectorx(vectorx));
bridge.initialize(1000000000000, IWrappedAvail(address(avail)), msg.sender, pauser, IVectorx(vectorx));
owner = msg.sender;
}

function test_owner() external {
assertEq(bridge.owner() != address(0), true);
assertEq(bridge.owner() == owner, true);
assertNotEq(bridge.owner(), address(0));
assertEq(bridge.owner(), owner);
}

function test_setFeePerByte(uint256 feePerByte) external {
vm.prank(owner);
bridge.updateFeePerByte(feePerByte);
assertEq(bridge.feePerByte(), feePerByte);
}

function test_updateVectorx(IVectorx newVectorx) external {
Expand Down Expand Up @@ -408,6 +414,43 @@ contract AvailBridgeTest is Test, MurkyBase {
assertEq(newBalance, balance + amount);
}

function testRevertExceedsMaxDataLength_sendMessage(bytes32 to, bytes[102_400] calldata c_data, uint256 amount) external {
bytes memory data = new bytes(c_data.length);
for (uint256 i = 0; i < c_data.length;) {
data[i] = bytes1(c_data[i]);
unchecked {
++i;
}
}
address from = makeAddr("from");
vm.prank(from);
vm.deal(from, amount);
vm.expectRevert(AvailBridge.ExceedsMaxDataLength.selector);
bridge.sendMessage{value: amount}(to, data);
assertEq(bridge.isSent(0), 0x0);
}

function testRevertFeeTooLow_sendMessage(bytes32 to, bytes calldata data, uint256 amount) external {
vm.assume(data.length < 102_400 && amount < bridge.getFee(data.length));
address from = makeAddr("from");
vm.prank(from);
vm.deal(from, amount);
vm.expectRevert(AvailBridge.FeeTooLow.selector);
bridge.sendMessage{value: amount}(to, data);
assertEq(bridge.isSent(0), 0x0);
}

function test_sendMessage(bytes32 to, bytes calldata data, uint256 amount) external {
vm.assume(data.length < 102_400 && amount >= 100000000000 * data.length);
address from = makeAddr("from");
AvailBridge.Message memory message =
AvailBridge.Message(0x01, bytes32(bytes20(from)), to, 2, 1, data, 0);
vm.prank(from);
vm.deal(from, amount);
bridge.sendMessage{value: amount}(to, data);
assertEq(bridge.isSent(0), keccak256(abi.encode(message)));
}

function test_sendAVL(bytes32 to, uint256 amount) external {
vm.assume(to != bytes32(0) && amount != 0);
address from = makeAddr("from");
Expand Down

0 comments on commit d431c28

Please sign in to comment.