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

add coverage for registrar and registry #12988

Merged
merged 2 commits into from
May 2, 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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
165 changes: 165 additions & 0 deletions contracts/src/v0.8/automation/dev/test/AutomationRegistrar2_3.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,97 @@ contract SetUp is BaseTest {

function setUp() public override {
super.setUp();
vm.startPrank(OWNER);
(registry, registrar) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN);
vm.stopPrank(); // reset identity at the start of each test
}
}

contract CancelUpkeep is SetUp {
function testUSDToken_happy() external {
vm.startPrank(UPKEEP_ADMIN);

uint96 amount = uint96(registrar.getMinimumRegistrationAmount(usdToken18));
usdToken18.approve(address(registrar), amount);

AutomationRegistrar2_3.RegistrationParams memory registrationParams = AutomationRegistrar2_3.RegistrationParams({
upkeepContract: address(TARGET1),
amount: amount,
adminAddress: UPKEEP_ADMIN,
gasLimit: 10_000,
triggerType: 0,
billingToken: usdToken18,
name: "foobar",
encryptedEmail: "",
checkData: bytes("check data"),
triggerConfig: "",
offchainConfig: ""
});

// default is auto approve off
registrar.registerUpkeep(registrationParams);

assertEq(usdToken18.balanceOf(address(registrar)), amount);
assertEq(registry.getNumUpkeeps(), 0);

uint256 startRegistrarBalance = usdToken18.balanceOf(address(registrar));
uint256 startUpkeepAdminBalance = usdToken18.balanceOf(UPKEEP_ADMIN);

// cancel the upkeep
vm.startPrank(OWNER);
bytes32 hash = keccak256(abi.encode(registrationParams));
registrar.cancel(hash);

uint256 endRegistrarBalance = usdToken18.balanceOf(address(registrar));
uint256 endUpkeepAdminBalance = usdToken18.balanceOf(UPKEEP_ADMIN);

assertEq(startRegistrarBalance - amount, endRegistrarBalance);
assertEq(startUpkeepAdminBalance + amount, endUpkeepAdminBalance);
}
}

contract ApproveUpkeep is SetUp {
function testUSDToken_happy() external {
vm.startPrank(UPKEEP_ADMIN);

uint96 amount = uint96(registrar.getMinimumRegistrationAmount(usdToken18));
usdToken18.approve(address(registrar), amount);

AutomationRegistrar2_3.RegistrationParams memory registrationParams = AutomationRegistrar2_3.RegistrationParams({
upkeepContract: address(TARGET1),
amount: amount,
adminAddress: UPKEEP_ADMIN,
gasLimit: 10_000,
triggerType: 0,
billingToken: usdToken18,
name: "foobar",
encryptedEmail: "",
checkData: bytes("check data"),
triggerConfig: "",
offchainConfig: ""
});

// default is auto approve off
registrar.registerUpkeep(registrationParams);

assertEq(usdToken18.balanceOf(address(registrar)), amount);
assertEq(registry.getNumUpkeeps(), 0);

uint256 startRegistrarBalance = usdToken18.balanceOf(address(registrar));
uint256 startRegistryBalance = usdToken18.balanceOf(address(registry));

// approve the upkeep
vm.startPrank(OWNER);
registrar.approve(registrationParams);

uint256 endRegistrarBalance = usdToken18.balanceOf(address(registrar));
uint256 endRegistryBalance = usdToken18.balanceOf(address(registry));

assertEq(startRegistrarBalance - amount, endRegistrarBalance);
assertEq(startRegistryBalance + amount, endRegistryBalance);
}
}

contract RegisterUpkeep is SetUp {
function testLink_autoApproveOff_happy() external {
vm.startPrank(UPKEEP_ADMIN);
Expand Down Expand Up @@ -75,6 +161,7 @@ contract RegisterUpkeep is SetUp {
}

function testLink_autoApproveOn_happy() external {
vm.startPrank(OWNER);
registrar.setTriggerConfig(0, AutomationRegistrar2_3.AutoApproveType.ENABLED_ALL, 1000);

vm.startPrank(UPKEEP_ADMIN);
Expand Down Expand Up @@ -103,6 +190,7 @@ contract RegisterUpkeep is SetUp {
}

function testUSDToken_autoApproveOn_happy() external {
vm.startPrank(OWNER);
registrar.setTriggerConfig(0, AutomationRegistrar2_3.AutoApproveType.ENABLED_ALL, 1000);

vm.startPrank(UPKEEP_ADMIN);
Expand Down Expand Up @@ -131,6 +219,7 @@ contract RegisterUpkeep is SetUp {
}

function testNative_autoApproveOn_happy() external {
vm.startPrank(OWNER);
registrar.setTriggerConfig(0, AutomationRegistrar2_3.AutoApproveType.ENABLED_ALL, 1000);

vm.startPrank(UPKEEP_ADMIN);
Expand Down Expand Up @@ -241,4 +330,80 @@ contract RegisterUpkeep is SetUp {
vm.expectRevert(AutomationRegistrar2_3.DuplicateEntry.selector);
registrar.registerUpkeep(params);
}

function test_revertOnInsufficientPayment() external {
vm.startPrank(UPKEEP_ADMIN);

// slightly less than the minimum amount
uint96 amount = uint96(registrar.getMinimumRegistrationAmount(IERC20(address(linkToken))) - 1);
linkToken.approve(address(registrar), amount);

AutomationRegistrar2_3.RegistrationParams memory params = AutomationRegistrar2_3.RegistrationParams({
upkeepContract: address(TARGET1),
amount: amount,
adminAddress: UPKEEP_ADMIN,
gasLimit: 10_000,
triggerType: 0,
billingToken: IERC20(address(linkToken)),
name: "foobar",
encryptedEmail: "",
checkData: bytes("check data"),
triggerConfig: "",
offchainConfig: ""
});

// attempt to register but revert bc of insufficient payment
vm.expectRevert(AutomationRegistrar2_3.InsufficientPayment.selector);
registrar.registerUpkeep(params);
}

function test_revertOnInvalidAdminAddress() external {
vm.startPrank(UPKEEP_ADMIN);

uint96 amount = uint96(registrar.getMinimumRegistrationAmount(IERC20(address(linkToken))));
linkToken.approve(address(registrar), amount);

AutomationRegistrar2_3.RegistrationParams memory params = AutomationRegistrar2_3.RegistrationParams({
upkeepContract: address(TARGET1),
amount: amount,
adminAddress: ZERO_ADDRESS, // zero address is invalid
gasLimit: 10_000,
triggerType: 0,
billingToken: IERC20(address(linkToken)),
name: "foobar",
encryptedEmail: "",
checkData: bytes("check data"),
triggerConfig: "",
offchainConfig: ""
});

// attempt to register but revert bc of invalid admin address
vm.expectRevert(AutomationRegistrar2_3.InvalidAdminAddress.selector);
registrar.registerUpkeep(params);
}

function test_revertOnInvalidBillingToken() external {
vm.startPrank(UPKEEP_ADMIN);

uint96 amount = 1;
usdToken18_2.approve(address(registrar), amount);

AutomationRegistrar2_3.RegistrationParams memory params = AutomationRegistrar2_3.RegistrationParams({
upkeepContract: address(TARGET1),
amount: amount,
adminAddress: UPKEEP_ADMIN,
gasLimit: 10_000,
triggerType: 0,
billingToken: IERC20(address(usdToken18_2)), // unsupported billing token
name: "foobar",
encryptedEmail: "",
checkData: bytes("check data"),
triggerConfig: "",
offchainConfig: ""
});

// attempt to register but revert bc of invalid admin address
vm.expectRevert(AutomationRegistrar2_3.InvalidBillingToken.selector);
registrar.registerUpkeep(params);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,69 @@ contract CheckUpkeep is SetUp {
}
}

contract WithdrawFunds is SetUp {
event FundsWithdrawn(uint256 indexed id, uint256 amount, address to);

function test_RevertsWhen_CalledByNonAdmin() external {
vm.expectRevert(Registry.OnlyCallableByAdmin.selector);
vm.prank(STRANGER);
registry.withdrawFunds(linkUpkeepID, STRANGER);
}

function test_RevertsWhen_InvalidRecipient() external {
vm.expectRevert(Registry.InvalidRecipient.selector);
vm.prank(UPKEEP_ADMIN);
registry.withdrawFunds(linkUpkeepID, ZERO_ADDRESS);
}

function test_RevertsWhen_UpkeepNotCanceled() external {
vm.expectRevert(Registry.UpkeepNotCanceled.selector);
vm.prank(UPKEEP_ADMIN);
registry.withdrawFunds(linkUpkeepID, UPKEEP_ADMIN);
}

function test_Happy_Link() external {
vm.startPrank(UPKEEP_ADMIN);
registry.cancelUpkeep(linkUpkeepID);
vm.roll(100 + block.number);

uint256 startUpkeepAdminBalance = linkToken.balanceOf(UPKEEP_ADMIN);
uint256 startLinkReserveAmountBalance = registry.getReserveAmount(address(linkToken));

uint256 upkeepBalance = registry.getBalance(linkUpkeepID);
vm.expectEmit();
emit FundsWithdrawn(linkUpkeepID, upkeepBalance, address(UPKEEP_ADMIN));
registry.withdrawFunds(linkUpkeepID, UPKEEP_ADMIN);

assertEq(registry.getBalance(linkUpkeepID), 0);
assertEq(linkToken.balanceOf(UPKEEP_ADMIN), startUpkeepAdminBalance + upkeepBalance);
assertEq(registry.getReserveAmount(address(linkToken)), startLinkReserveAmountBalance - upkeepBalance);
}

function test_Happy_USDToken() external {
vm.startPrank(UPKEEP_ADMIN);
registry.cancelUpkeep(usdUpkeepID6);
vm.roll(100 + block.number);

uint256 startUpkeepAdminBalance = usdToken6.balanceOf(UPKEEP_ADMIN);
uint256 startUSDToken6ReserveAmountBalance = registry.getReserveAmount(address(usdToken6));

uint256 upkeepBalance = registry.getBalance(usdUpkeepID6);
vm.expectEmit();
emit FundsWithdrawn(usdUpkeepID6, upkeepBalance, address(UPKEEP_ADMIN));
registry.withdrawFunds(usdUpkeepID6, UPKEEP_ADMIN);

assertEq(registry.getBalance(usdUpkeepID6), 0);
assertEq(usdToken6.balanceOf(UPKEEP_ADMIN), startUpkeepAdminBalance + upkeepBalance);
assertEq(registry.getReserveAmount(address(usdToken6)), startUSDToken6ReserveAmountBalance - upkeepBalance);
}
}

contract AddFunds is SetUp {
event FundsAdded(uint256 indexed id, address indexed from, uint96 amount);

// when msg.value is 0, it uses the ERC20 payment path
function testNative_msgValue0() external {
function test_HappyWhen_NativeUpkeep_WithMsgValue0() external {
vm.startPrank(OWNER);
uint256 startRegistryBalance = registry.getBalance(nativeUpkeepID);
uint256 startTokenBalance = registry.getBalance(nativeUpkeepID);
Expand All @@ -150,7 +208,7 @@ contract AddFunds is SetUp {
}

// when msg.value is not 0, it uses the native payment path
function testNative_msgValueNot0() external {
function test_HappyWhen_NativeUpkeep_WithMsgValueNot0() external {
uint256 startRegistryBalance = registry.getBalance(nativeUpkeepID);
uint256 startTokenBalance = registry.getBalance(nativeUpkeepID);
registry.addFunds{value: 1}(nativeUpkeepID, 1000); // parameter amount should be ignored
Expand Down
4 changes: 4 additions & 0 deletions contracts/src/v0.8/automation/dev/test/BaseTest.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ contract BaseTest is Test {
LinkToken internal linkToken;
ERC20Mock6Decimals internal usdToken6;
ERC20Mock internal usdToken18;
ERC20Mock internal usdToken18_2;
WETH9 internal weth;
MockV3Aggregator internal LINK_USD_FEED;
MockV3Aggregator internal NATIVE_USD_FEED;
Expand Down Expand Up @@ -76,6 +77,7 @@ contract BaseTest is Test {
linkToken = new LinkToken();
linkToken.grantMintRole(OWNER);
usdToken18 = new ERC20Mock("MOCK_ERC20_18Decimals", "MOCK_ERC20_18Decimals", OWNER, 0);
usdToken18_2 = new ERC20Mock("Second_MOCK_ERC20_18Decimals", "Second_MOCK_ERC20_18Decimals", OWNER, 0);
usdToken6 = new ERC20Mock6Decimals("MOCK_ERC20_6Decimals", "MOCK_ERC20_6Decimals", OWNER, 0);
weth = new WETH9();

Expand Down Expand Up @@ -128,6 +130,8 @@ contract BaseTest is Test {
usdToken18.mint(FINANCE_ADMIN, 1000e18);
usdToken18.mint(STRANGER, 1000e18);

usdToken18_2.mint(UPKEEP_ADMIN, 1000e18);

usdToken6.mint(OWNER, 1000e6);
usdToken6.mint(UPKEEP_ADMIN, 1000e6);
usdToken6.mint(FINANCE_ADMIN, 1000e6);
Expand Down