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 claim to Sale #202

Merged
merged 1 commit into from
Apr 11, 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
1 change: 1 addition & 0 deletions packages/contracts/contracts/test/MockSale.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ contract MockSale is ISale, ERC165 {
mapping(address => uint256) public override(ISale) refundAmount;
mapping(string => uint256) public calls;

address public token;
address public paymentToken;

function paymentTokenToToken(
Expand Down
5 changes: 4 additions & 1 deletion packages/contracts/contracts/token/ISale.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
pragma solidity ^0.8.20;

interface ISale {
/// The $aUSD token
/// The $CTND token
function token() external view returns (address);

/// The $USDC token
function paymentToken() external view returns (address);

/// How many $CTND will be received for the given payment amount
Expand Down
34 changes: 33 additions & 1 deletion packages/contracts/contracts/token/Sale.sol
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ contract Sale is ISale, RisingTide, ERC165, AccessControl, ReentrancyGuard {
uint256 tokenAmount
);

/// Emitted for every claim
event Claim(address indexed to, uint256 tokenAmount);

/// Emitted for every refund given
event Refund(address indexed to, uint256 paymentTokenAmount);

Expand All @@ -56,6 +59,9 @@ contract Sale is ISale, RisingTide, ERC165, AccessControl, ReentrancyGuard {
// State
//

/// See {ISale.token}
address public override(ISale) token;

/// See {ISale.paymentToken}
address public immutable override(ISale) paymentToken;

Expand Down Expand Up @@ -153,6 +159,11 @@ contract Sale is ISale, RisingTide, ERC165, AccessControl, ReentrancyGuard {
_grantRole(CAP_VALIDATOR_ROLE, msg.sender);
}

modifier beforeSale() {
require(block.timestamp <= start, "sale active");
_;
}

/// Ensures we're running during the set sale period
modifier inSale() {
require(
Expand Down Expand Up @@ -240,10 +251,25 @@ contract Sale is ISale, RisingTide, ERC165, AccessControl, ReentrancyGuard {
);
}

function claim() external capCalculated nonReentrant {
Account storage account = accounts[msg.sender];
require(!account.refunded, "already claimed");

if (refundAmount(msg.sender) != 0) {
refund(msg.sender);
}

uint256 capped = allocation(msg.sender);

IERC20(token).transfer(msg.sender, capped);

emit Claim(msg.sender, capped);
}

/// @inheritdoc ISale
function refund(
address to
) external override(ISale) capCalculated nonReentrant {
) public override(ISale) capCalculated nonReentrant {
Account storage account = accounts[to];
require(!account.refunded, "already refunded");

Expand Down Expand Up @@ -336,6 +362,12 @@ contract Sale is ISale, RisingTide, ERC165, AccessControl, ReentrancyGuard {
// Admin API
//

function setToken(
address _token
) external onlyRole(DEFAULT_ADMIN_ROLE) beforeSale nonReentrant {
token = _token;
}

/// Sets the individual cap
/// @dev Can only be called once
///
Expand Down
4 changes: 2 additions & 2 deletions packages/contracts/script/Deploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ contract DeployScript is Script {

uint256 start = vm.unixTime();
uint256 end = start + 60 * 60 * 24 * 7;
uint256 startRegistration = 1714089600;
uint256 endRegistration = 1714694400;
uint256 startRegistration = 1714089600000;
uint256 endRegistration = 1714694400000;

MockERC20 token = new MockERC20("USDC", "USDC", 18);
Sale sale = new Sale(
Expand Down
8 changes: 5 additions & 3 deletions packages/contracts/script/DevDeploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ contract DevDeployScript is Script {

bytes32 merkleRoot = 0xa5c09e2a9128afef7246a5900cfe02c4bd2cfcac8ac4286f0159a699c8455a49;

startRegistration = 1714089600;
endRegistration = 1714694400;
startRegistration = 1714089600000;
endRegistration = 1714694400000;

start = vm.getBlockTimestamp();
end = start + 60 * 60 * 24;
Expand All @@ -49,13 +49,15 @@ contract DevDeployScript is Script {
1 ** 18,
start,
end,
1000,
100000000000000000000,
1000000,
2000000,
startRegistration,
endRegistration
);

bool sucesss = citizend.transfer(address(sale), 1000 ether);

bool success = token.approve(address(sale), 1000 ether);
require(success, "approve failed");

Expand Down
35 changes: 34 additions & 1 deletion packages/contracts/test/contracts/token/Sale.d.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ pragma solidity ^0.8.20;
import "forge-std/Test.sol";

import {Sale} from "../../../contracts/token/Sale.sol";
import {Citizend} from "../../../contracts/token/Citizend.sol";
import {MockERC20} from "../../../contracts/test/MockERC20.sol";

contract SaleTest is Test {
Sale sale;
Citizend token;
MockERC20 paymentToken;
uint256 start;
uint256 end;
Expand All @@ -23,6 +25,8 @@ contract SaleTest is Test {
uint256 tokenAmount
);

event Claim(address indexed to, uint256 tokenAmount);

function setUp() public {
vm.startPrank(owner);

Expand All @@ -33,20 +37,24 @@ contract SaleTest is Test {
end = start + 60 * 60 * 24;

paymentToken = new MockERC20("USDC", "USDC", 18);
token = new Citizend(owner);
sale = new Sale(
address(paymentToken),
1 ** 18,
start,
end,
100,
1000000000000000000000000,
1000000,
2000000,
startRegistration,
endRegistration
);

sale.setToken(address(token));
sale.setMaxContribution(4 ether);

token.transfer(address(sale), 1000000 ether);

vm.stopPrank();

vm.startPrank(alice);
Expand Down Expand Up @@ -111,4 +119,29 @@ contract SaleTest is Test {

vm.stopPrank();
}

function testBuyAndClaim() public {
require(token.balanceOf(alice) == 0 ether);

vm.prank(alice);
sale.buy(2 ether);

vm.warp(end + 1000);

require(sale.uncappedAllocation(address(alice)) == 2 ether);

vm.prank(owner);
sale.setIndividualCap(2 ether);

require(sale.risingTide_isValidCap(), "not valid cap");
require(sale.allocation(address(alice)) == 2 ether);

vm.expectEmit();
emit Claim(address(alice), 2 ether);

vm.prank(alice);
sale.claim();

require(token.balanceOf(alice) == 2 ether);
}
}
Loading
Loading