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

audit: merge all audit changes #4

Merged
merged 8 commits into from
Feb 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 4 additions & 4 deletions script/Deploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import {TransparentUpgradeableProxy} from
"lib/openzeppelin-contracts/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
import {ProxyAdmin} from "lib/openzeppelin-contracts/contracts/proxy/transparent/ProxyAdmin.sol";
import {AvailBridge} from "src/AvailBridge.sol";
import {WrappedAvail} from "src/WrappedAvail.sol";
import {IWrappedAvail} from "src/interfaces/IWrappedAvail.sol";
import {Avail} from "src/Avail.sol";
import {IAvail} from "src/interfaces/IAvail.sol";
import {IVectorx} from "src/interfaces/IVectorx.sol";
import {Script} from "forge-std/Script.sol";

Expand All @@ -18,8 +18,8 @@ contract GetProofMockScript is Script {
ProxyAdmin proxyAdmin = new ProxyAdmin(admin);
address impl = address(new AvailBridge());
AvailBridge bridge = AvailBridge(address(new TransparentUpgradeableProxy(impl, address(proxyAdmin), "")));
WrappedAvail avail = new WrappedAvail(address(bridge));
bridge.initialize(0, admin, IWrappedAvail(address(avail)), admin, admin, IVectorx(vectorx));
Avail avail = new Avail(address(bridge));
bridge.initialize(0, admin, IAvail(address(avail)), admin, admin, IVectorx(vectorx));
vm.stopBroadcast();
}
}
8 changes: 4 additions & 4 deletions script/DeployMock.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import {TransparentUpgradeableProxy} from
"lib/openzeppelin-contracts/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
import {ProxyAdmin} from "lib/openzeppelin-contracts/contracts/proxy/transparent/ProxyAdmin.sol";
import {DummyAvailBridge} from "src/mocks/DummyAvailBridge.sol";
import {WrappedAvail} from "src/WrappedAvail.sol";
import {IWrappedAvail} from "src/interfaces/IWrappedAvail.sol";
import {Avail} from "src/Avail.sol";
import {IAvail} from "src/interfaces/IAvail.sol";
import {IDummyVectorx} from "src/mocks/interfaces/IDummyVectorx.sol";
import {Script} from "forge-std/Script.sol";

Expand All @@ -19,8 +19,8 @@ contract GetProofMockScript is Script {
address impl = address(new DummyAvailBridge());
DummyAvailBridge bridge =
DummyAvailBridge(address(new TransparentUpgradeableProxy(impl, address(proxyAdmin), "")));
WrappedAvail avail = new WrappedAvail(address(bridge));
bridge.initialize(0, admin, IWrappedAvail(address(avail)), admin, admin, IDummyVectorx(vectorx));
Avail avail = new Avail(address(bridge));
bridge.initialize(0, admin, IAvail(address(avail)), admin, admin, IDummyVectorx(vectorx));
vm.stopBroadcast();
}
}
4 changes: 2 additions & 2 deletions script/GetProofMockScript.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {ProxyAdmin} from "lib/openzeppelin-contracts/contracts/proxy/transparent
import {AvailBridge} from "src/AvailBridge.sol";
import {IAvailBridge} from "src/interfaces/IAvailBridge.sol";
import {ERC20Mock} from "src/mocks/ERC20Mock.sol";
import {IWrappedAvail} from "src/interfaces/IWrappedAvail.sol";
import {IAvail} from "src/interfaces/IAvail.sol";
import {VectorxMock, IVectorx} from "src/mocks/VectorxMock.sol";
import {Script} from "forge-std/Script.sol";
import {console} from "forge-std/console.sol";
Expand All @@ -20,7 +20,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(0, msg.sender, IWrappedAvail(address(avail)), msg.sender, msg.sender, IVectorx(vectorx));
bridge.initialize(0, msg.sender, IAvail(address(avail)), msg.sender, msg.sender, IVectorx(vectorx));
avail.mint(msg.sender, 1 ether);
bridge.sendAVAIL(bytes32(uint256(1)), 1 ether);
console.logBytes32(bridge.isSent(0));
Expand Down
4 changes: 2 additions & 2 deletions script/SendMessage.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import {TransparentUpgradeableProxy} from
import {ProxyAdmin} from "lib/openzeppelin-contracts/contracts/proxy/transparent/ProxyAdmin.sol";
import {AvailBridge} from "src/AvailBridge.sol";
import {IAvailBridge} from "src/interfaces/IAvailBridge.sol";
import {WrappedAvail} from "src/WrappedAvail.sol";
import {IWrappedAvail} from "src/interfaces/IWrappedAvail.sol";
import {Avail} from "src/Avail.sol";
import {IAvail} from "src/interfaces/IAvail.sol";
import {IVectorx} from "src/interfaces/IVectorx.sol";
import {Script} from "forge-std/Script.sol";
import {console} from "forge-std/console.sol";
Expand Down
8 changes: 4 additions & 4 deletions src/WrappedAvail.sol → src/Avail.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,20 @@
pragma solidity ^0.8.23;

import {ERC20, ERC20Permit} from "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Permit.sol";
import {IWrappedAvail} from "src/interfaces/IWrappedAvail.sol";
import {IAvail} from "src/interfaces/IAvail.sol";

/**
* @author @QEDK (Avail)
* @title WrappedAvail
* @title Avail ERC20 token
* @notice An Avail token implementation for Ethereum
* @custom:security security@availproject.org
*/
contract WrappedAvail is ERC20Permit, IWrappedAvail {
contract Avail is ERC20Permit, IAvail {
address public immutable bridge;

error OnlyAvailBridge();

constructor(address _bridge) ERC20Permit("Wrapped Avail") ERC20("WAVAIL", "Wrapped Avail") {
constructor(address _bridge) ERC20Permit("Avail") ERC20("Avail", "AVAIL") {
// slither-disable-next-line missing-zero-check
bridge = _bridge;
}
Expand Down
12 changes: 6 additions & 6 deletions src/AvailBridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {SafeERC20} from "lib/openzeppelin-contracts/contracts/token/ERC20/utils/
import {IERC20} from "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
import {Merkle} from "src/lib/Merkle.sol";
import {IVectorx} from "src/interfaces/IVectorx.sol";
import {IWrappedAvail} from "src/interfaces/IWrappedAvail.sol";
import {IAvail} from "src/interfaces/IAvail.sol";
import {IMessageReceiver} from "src/interfaces/IMessageReceiver.sol";
import {IAvailBridge} from "src/interfaces/IAvailBridge.sol";

Expand Down Expand Up @@ -48,7 +48,7 @@ contract AvailBridge is
mapping(bytes32 => address) public tokens;

IVectorx public vectorx;
IWrappedAvail public avail;
IAvail public avail;
address public feeRecipient;
uint256 public fees; // total fees accumulated by bridge
uint256 public feePerByte; // in wei
Expand All @@ -69,7 +69,7 @@ contract AvailBridge is
}

modifier checkDestAmt(bytes32 dest, uint256 amount) {
if (dest == 0x0 || amount == 0) {
if (dest == 0x0 || amount == 0 || amount > type(uint128).max) {
revert InvalidDestinationOrAmount();
}
_;
Expand All @@ -87,7 +87,7 @@ contract AvailBridge is
function initialize(
uint256 newFeePerByte,
address newFeeRecipient,
IWrappedAvail newAvail,
IAvail newAvail,
address governance,
address pauser,
IVectorx newVectorx
Expand Down Expand Up @@ -299,8 +299,8 @@ contract AvailBridge is
*/
function sendMessage(bytes32 recipient, bytes calldata data) external payable whenNotPaused {
uint256 length = data.length;
if (length >= MAX_DATA_LENGTH) {
revert ExceedsMaxDataLength();
if (length == 0 || length > MAX_DATA_LENGTH) {
revert InvalidDataLength();
}
// ensure that fee is above minimum amount
if (msg.value < getFee(length)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pragma solidity ^0.8.23;

import {IERC20} from "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";

interface IWrappedAvail is IERC20 {
interface IAvail is IERC20 {
function mint(address destination, uint256 amount) external;
function burn(address from, uint256 amount) external;
}
2 changes: 1 addition & 1 deletion src/interfaces/IAvailBridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ interface IAvailBridge {
error BlobRootEmpty();
error BridgeRootEmpty();
error DataRootCommitmentEmpty();
error ExceedsMaxDataLength();
error FeeTooLow();
error InvalidAssetId();
error InvalidDataLength();
error InvalidDataRootProof();
error InvalidDomain();
error InvalidDestinationOrAmount();
Expand Down
10 changes: 5 additions & 5 deletions src/mocks/DummyAvailBridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {SafeERC20} from "lib/openzeppelin-contracts/contracts/token/ERC20/utils/
import {IERC20} from "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
import {Merkle} from "src/lib/Merkle.sol";
import {IDummyVectorx} from "src/mocks/interfaces/IDummyVectorx.sol";
import {IWrappedAvail} from "src/interfaces/IWrappedAvail.sol";
import {IAvail} from "src/interfaces/IAvail.sol";
import {IMessageReceiver} from "src/interfaces/IMessageReceiver.sol";
import {IAvailBridge} from "src/interfaces/IAvailBridge.sol";

Expand Down Expand Up @@ -48,7 +48,7 @@ contract DummyAvailBridge is
mapping(bytes32 => address) public tokens;

IDummyVectorx public vectorx;
IWrappedAvail public avail;
IAvail public avail;
address public feeRecipient;
uint256 public fees; // total fees accumulated by bridge
uint256 public feePerByte; // in wei
Expand Down Expand Up @@ -88,7 +88,7 @@ contract DummyAvailBridge is
function initialize(
uint256 newFeePerByte,
address newFeeRecipient,
IWrappedAvail newAvail,
IAvail newAvail,
address governance,
address pauser,
IDummyVectorx newVectorx
Expand Down Expand Up @@ -309,8 +309,8 @@ contract DummyAvailBridge is
*/
function sendMessage(bytes32 recipient, bytes calldata data) external payable whenNotPaused {
uint256 length = data.length;
if (length > MAX_DATA_LENGTH) {
revert ExceedsMaxDataLength();
if (length == 0 || length > MAX_DATA_LENGTH) {
revert InvalidDataLength();
}
// ensure that fee is above minimum amount
if (msg.value < getFee(length)) {
Expand Down
62 changes: 48 additions & 14 deletions test/AvailBridgeTest.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {ProxyAdmin} from "lib/openzeppelin-contracts/contracts/proxy/transparent
import {IAccessControl} from "lib/openzeppelin-contracts/contracts/access/IAccessControl.sol";
import {Pausable} from "lib/openzeppelin-contracts/contracts/utils/Pausable.sol";
import {IAvailBridge, AvailBridge} from "src/AvailBridge.sol";
import {WrappedAvail, IWrappedAvail} from "src/WrappedAvail.sol";
import {Avail, IAvail} from "src/Avail.sol";
import {VectorxMock, IVectorx} from "src/mocks/VectorxMock.sol";
import {ERC20Mock} from "src/mocks/ERC20Mock.sol";
import {MessageReceiverMock} from "src/mocks/MessageReceiverMock.sol";
Expand All @@ -16,7 +16,7 @@ import {Vm, Test, console} from "forge-std/Test.sol";

contract AvailBridgeTest is Test, MurkyBase {
AvailBridge public bridge;
WrappedAvail public avail;
Avail public avail;
VectorxMock public vectorx;
ProxyAdmin public admin;
Sha2Merkle public sha2merkle;
Expand All @@ -31,8 +31,8 @@ contract AvailBridgeTest is Test, MurkyBase {
sha2merkle = new Sha2Merkle();
address impl = address(new AvailBridge());
bridge = AvailBridge(address(new TransparentUpgradeableProxy(impl, address(admin), "")));
avail = new WrappedAvail(address(bridge));
bridge.initialize(0, msg.sender, IWrappedAvail(address(avail)), msg.sender, pauser, IVectorx(vectorx));
avail = new Avail(address(bridge));
bridge.initialize(0, msg.sender, IAvail(address(avail)), msg.sender, pauser, IVectorx(vectorx));
owner = msg.sender;
}

Expand Down Expand Up @@ -596,19 +596,31 @@ contract AvailBridgeTest is Test, MurkyBase {
assertTrue(bridge.isBridged(messageHash));
}

function testRevertExceedsMaxDataLength_sendMessage(bytes32 to, bytes32[3200] calldata c_data, uint256 amount)
function testRevertInvalidDataLength_sendMessage(bytes32 to, bytes32[3201] calldata c_data, uint256 amount)
external
{
bytes memory data = abi.encode(c_data);
bytes memory data = abi.encodePacked(c_data);
address from = makeAddr("from");
vm.prank(from);
vm.deal(from, amount);
vm.expectRevert(IAvailBridge.ExceedsMaxDataLength.selector);
vm.expectRevert(IAvailBridge.InvalidDataLength.selector);
bridge.sendMessage{value: amount}(to, data);
assertEq(bridge.isSent(0), 0x0);
assertEq(bridge.fees(), 0);
}

function testRevertInvalidDataLength_sendMessage(bytes32 to, uint256 amount)
external
{
address from = makeAddr("from");
vm.prank(from);
vm.deal(from, amount);
vm.expectRevert(IAvailBridge.InvalidDataLength.selector);
bridge.sendMessage{value: amount}(to, "");
assertEq(bridge.isSent(0), 0x0);
assertEq(bridge.fees(), 0);
}

function testRevertFeeTooLow_sendMessage(bytes32 to, bytes calldata data, uint32 feePerByte, uint256 amount)
external
{
Expand All @@ -628,7 +640,7 @@ contract AvailBridgeTest is Test, MurkyBase {
function test_sendMessage(bytes32 to, bytes calldata data, uint32 feePerByte, uint256 amount) external {
vm.prank(owner);
bridge.updateFeePerByte(feePerByte);
vm.assume(data.length < 102_400 && amount >= bridge.getFee(data.length));
vm.assume(data.length != 0 && data.length < 102_400 && amount >= bridge.getFee(data.length));
address from = makeAddr("from");
IAvailBridge.Message memory message = IAvailBridge.Message(0x01, bytes32(bytes20(from)), to, 2, 1, data, 0);
vm.prank(from);
Expand All @@ -643,7 +655,7 @@ contract AvailBridgeTest is Test, MurkyBase {
{
vm.prank(owner);
bridge.updateFeePerByte(feePerByte);
vm.assume(data.length < 102_400 && amount >= bridge.getFee(data.length));
vm.assume(data.length != 0 && data.length < 102_400 && amount >= bridge.getFee(data.length));
address from = makeAddr("from");
IAvailBridge.Message memory message = IAvailBridge.Message(0x01, bytes32(bytes20(from)), to, 2, 1, data, 0);
vm.prank(from);
Expand All @@ -663,7 +675,7 @@ contract AvailBridgeTest is Test, MurkyBase {
function test_withdrawFees(bytes32 to, bytes calldata data, uint32 feePerByte, uint248 amount) external {
vm.prank(owner);
bridge.updateFeePerByte(feePerByte);
vm.assume(data.length < 102_400 && amount >= bridge.getFee(data.length));
vm.assume(data.length != 0 && data.length < 102_400 && amount >= bridge.getFee(data.length));
address from = makeAddr("from");
IAvailBridge.Message memory message = IAvailBridge.Message(0x01, bytes32(bytes20(from)), to, 2, 1, data, 0);
vm.prank(from);
Expand All @@ -678,7 +690,7 @@ contract AvailBridgeTest is Test, MurkyBase {
assertEq(bridge.fees(), 0);
}

function test_sendAVAIL(bytes32 to, uint256 amount) external {
function test_sendAVAIL(bytes32 to, uint128 amount) external {
vm.assume(to != bytes32(0) && amount != 0);
address from = makeAddr("from");
vm.prank(address(bridge));
Expand All @@ -693,7 +705,7 @@ contract AvailBridgeTest is Test, MurkyBase {
assertEq(avail.totalSupply(), 0);
}

function test_sendETH(bytes32 to, uint256 amount) external {
function test_sendETH(bytes32 to, uint128 amount) external {
vm.assume(to != bytes32(0) && amount != 0);
address from = makeAddr("from");
vm.deal(from, amount);
Expand All @@ -715,13 +727,35 @@ contract AvailBridgeTest is Test, MurkyBase {
assertEq(bridge.messageId(), 1);
}

function testRevertInvalidAssetId_sendERC20(bytes32 assetId, bytes32 dest, uint256 amount) external {
function testRevertInvalidAssetId_sendERC20(bytes32 assetId, bytes32 dest, uint128 amount) external {
vm.assume(dest != 0x0 && amount != 0);
vm.expectRevert(IAvailBridge.InvalidAssetId.selector);
bridge.sendERC20(assetId, dest, amount);
}

function test_sendERC20(bytes32 assetId, bytes32 to, uint256 amount) external {
function testRevertInvalidDestinationOrAmount_sendERC20(bytes32 assetId, bytes32 to, uint256 amount) external {
vm.assume(to != bytes32(0) && amount > type(uint128).max);
address from = makeAddr("from");
ERC20Mock token = new ERC20Mock();
token.mint(from, amount);
bytes32[] memory assetIdArr = new bytes32[](1);
assetIdArr[0] = assetId;
address[] memory tokenArr = new address[](1);
tokenArr[0] = address(token);
vm.prank(owner);
bridge.updateTokens(assetIdArr, tokenArr);
vm.startPrank(from);
vm.expectRevert(IAvailBridge.InvalidDestinationOrAmount.selector);
bridge.sendERC20(assetId, 0x0, uint128(amount));
vm.expectRevert(IAvailBridge.InvalidDestinationOrAmount.selector);
bridge.sendERC20(assetId, to, amount);
vm.expectRevert(IAvailBridge.InvalidDestinationOrAmount.selector);
bridge.sendERC20(assetId, 0x0, amount);
assertEq(bridge.isSent(0), 0x0);
assertEq(token.balanceOf(address(bridge)), 0);
}

function test_sendERC20(bytes32 assetId, bytes32 to, uint128 amount) external {
vm.assume(to != bytes32(0) && amount != 0);
address from = makeAddr("from");
ERC20Mock token = new ERC20Mock();
Expand Down
17 changes: 11 additions & 6 deletions test/WrappedAvailTest.t.sol → test/AvailTest.t.sol
Original file line number Diff line number Diff line change
@@ -1,22 +1,27 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.23;

import {WrappedAvail} from "src/WrappedAvail.sol";
import {Avail} from "src/Avail.sol";
import {Vm, Test} from "forge-std/Test.sol";

contract WrappedAvailTest is Test {
WrappedAvail public avail;
contract AvailTest is Test {
Avail public avail;
address public bridge;

function setUp() external {
bridge = makeAddr("bridge");
avail = new WrappedAvail(bridge);
avail = new Avail(bridge);
}

function test_nameSymbol() external {
assertEq(avail.name(), "Avail");
assertEq(avail.symbol(), "AVAIL");
}

function testRevertOnlyAvailBridge_mint(address sender, address dest, uint256 amount) external {
vm.assume(dest != address(0) && sender != bridge);
vm.prank(sender);
vm.expectRevert(WrappedAvail.OnlyAvailBridge.selector);
vm.expectRevert(Avail.OnlyAvailBridge.selector);
avail.mint(dest, amount);
assertEq(avail.balanceOf(dest), 0);
}
Expand All @@ -31,7 +36,7 @@ contract WrappedAvailTest is Test {
function testRevertOnlyAvailBridge_burn(address sender, address dest, uint256 amount) external {
vm.assume(dest != address(0) && sender != bridge);
vm.prank(sender);
vm.expectRevert(WrappedAvail.OnlyAvailBridge.selector);
vm.expectRevert(Avail.OnlyAvailBridge.selector);
avail.burn(dest, amount);
assertEq(avail.balanceOf(dest), 0);
}
Expand Down