The home for Hyperlane core contracts, sdk packages, and other infrastructure
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
hyperlane-monorepo/solidity/test/token/HypNativeScaled.t.sol

217 lines
7.0 KiB

// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.8.0;
import "forge-std/Test.sol";
import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
import {TestPostDispatchHook} from "../../contracts/test/TestPostDispatchHook.sol";
import {HypNativeScaled} from "../../contracts/token/extensions/HypNativeScaled.sol";
import {HypERC20} from "../../contracts/token/HypERC20.sol";
import {HypNative} from "../../contracts/token/HypNative.sol";
import {TypeCasts} from "../../contracts/libs/TypeCasts.sol";
import {MockHyperlaneEnvironment} from "../../contracts/mock/MockHyperlaneEnvironment.sol";
contract HypNativeScaledTest is Test {
uint32 nativeDomain = 1;
uint32 synthDomain = 2;
address internal constant ALICE = address(0x1);
uint8 decimals = 9;
uint256 mintAmount = 123456789;
uint256 nativeDecimals = 18;
uint256 scale = 10 ** (nativeDecimals - decimals);
event Donation(address indexed sender, uint256 amount);
event SentTransferRemote(
uint32 indexed destination,
bytes32 indexed recipient,
uint256 amount
);
event ReceivedTransferRemote(
uint32 indexed origin,
bytes32 indexed recipient,
uint256 amount
);
HypNativeScaled native;
HypERC20 synth;
MockHyperlaneEnvironment environment;
function setUp() public {
environment = new MockHyperlaneEnvironment(synthDomain, nativeDomain);
HypERC20 implementationSynth = new HypERC20(
decimals,
address(environment.mailboxes(synthDomain))
);
TransparentUpgradeableProxy proxySynth = new TransparentUpgradeableProxy(
address(implementationSynth),
address(9),
abi.encodeWithSelector(
HypERC20.initialize.selector,
mintAmount * (10 ** decimals),
"Zebec BSC Token",
"ZBC",
address(0),
address(0),
address(this)
)
);
synth = HypERC20(address(proxySynth));
HypNativeScaled implementationNative = new HypNativeScaled(
scale,
address(environment.mailboxes(nativeDomain))
);
TransparentUpgradeableProxy proxyNative = new TransparentUpgradeableProxy(
address(implementationNative),
address(9),
abi.encodeWithSelector(
HypNative.initialize.selector,
address(0),
address(0),
address(this)
)
);
native = HypNativeScaled(payable(address(proxyNative)));
native.enrollRemoteRouter(
synthDomain,
TypeCasts.addressToBytes32(address(synth))
);
synth.enrollRemoteRouter(
nativeDomain,
TypeCasts.addressToBytes32(address(native))
);
}
function test_constructor() public {
assertEq(native.scale(), scale);
}
uint256 receivedValue;
receive() external payable {
receivedValue = msg.value;
}
function test_receive(uint256 amount) public {
vm.assume(amount < address(this).balance);
vm.expectEmit(true, true, true, true);
emit Donation(address(this), amount);
(bool success, bytes memory returnData) = address(native).call{
value: amount
}("");
assert(success);
assertEq(returnData.length, 0);
}
function test_handle(uint256 amount) public {
vm.assume(amount <= mintAmount);
uint256 synthAmount = amount * (10 ** decimals);
uint256 nativeAmount = amount * (10 ** nativeDecimals);
vm.deal(address(native), nativeAmount);
bytes32 recipient = TypeCasts.addressToBytes32(address(this));
synth.transferRemote(nativeDomain, recipient, synthAmount);
vm.expectEmit(true, true, true, true);
emit ReceivedTransferRemote(synthDomain, recipient, synthAmount);
environment.processNextPendingMessage();
assertEq(receivedValue, nativeAmount);
}
function test_handle_reverts_whenAmountExceedsSupply(
uint256 amount
) public {
vm.assume(amount <= mintAmount);
bytes32 recipient = TypeCasts.addressToBytes32(address(this));
synth.transferRemote(nativeDomain, recipient, amount);
uint256 nativeValue = amount * scale;
vm.deal(address(native), nativeValue / 2);
if (amount > 0) {
vm.expectRevert(bytes("Address: insufficient balance"));
}
environment.processNextPendingMessage();
}
function test_tranferRemote(uint256 amount) public {
vm.assume(amount <= mintAmount);
uint256 nativeValue = amount * (10 ** nativeDecimals);
uint256 synthAmount = amount * (10 ** decimals);
address recipient = address(0xdeadbeef);
bytes32 bRecipient = TypeCasts.addressToBytes32(recipient);
vm.deal(address(this), nativeValue);
vm.expectEmit(true, true, true, true);
emit SentTransferRemote(synthDomain, bRecipient, synthAmount);
native.transferRemote{value: nativeValue}(
synthDomain,
bRecipient,
nativeValue
);
environment.processNextPendingMessageFromDestination();
assertEq(synth.balanceOf(recipient), synthAmount);
}
function testTransfer_withHookSpecified(
uint256 amount,
bytes calldata metadata
) public {
vm.assume(amount <= mintAmount);
uint256 nativeValue = amount * (10 ** nativeDecimals);
uint256 synthAmount = amount * (10 ** decimals);
address recipient = address(0xdeadbeef);
bytes32 bRecipient = TypeCasts.addressToBytes32(recipient);
TestPostDispatchHook hook = new TestPostDispatchHook();
vm.deal(address(this), nativeValue);
vm.expectEmit(true, true, true, true);
emit SentTransferRemote(synthDomain, bRecipient, synthAmount);
native.transferRemote{value: nativeValue}(
synthDomain,
bRecipient,
nativeValue,
metadata,
address(hook)
);
environment.processNextPendingMessageFromDestination();
assertEq(synth.balanceOf(recipient), synthAmount);
}
function test_transferRemote_reverts_whenAmountExceedsValue(
uint256 nativeValue
) public {
vm.assume(nativeValue < address(this).balance);
address recipient = address(0xdeadbeef);
bytes32 bRecipient = TypeCasts.addressToBytes32(recipient);
vm.expectRevert("Native: amount exceeds msg.value");
native.transferRemote{value: nativeValue}(
synthDomain,
bRecipient,
nativeValue + 1
);
vm.expectRevert("Native: amount exceeds msg.value");
native.transferRemote{value: nativeValue}(
synthDomain,
bRecipient,
nativeValue + 1,
bytes(""),
address(0)
);
}
}