Skip to content
This repository was archived by the owner on Apr 4, 2025. It is now read-only.

Commit d9f0c11

Browse files
authored
Merge pull request #36 from code-423n4/feature/fixSaleAmount
Make buy token sale amount fixed
2 parents 6f267cf + b381804 commit d9f0c11

File tree

2 files changed

+18
-61
lines changed

2 files changed

+18
-61
lines changed

contracts/ArenaTokenSale.sol

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -77,22 +77,14 @@ contract TokenSale is Ownable {
7777

7878
/**
7979
* @dev Whitelisted buyers can buy `tokenOutAmount` tokens at the `tokenOutPrice`.
80-
* @param _tokenOutAmount The amount of `tokenOut` to buy
8180
* @return tokenInAmount_ The amount of `tokenIn`s bought.
8281
*/
83-
function buy(uint256 _tokenOutAmount) external returns (uint256 tokenInAmount_) {
82+
function buy() external returns (uint256 tokenInAmount_) {
8483
require(saleStart <= block.timestamp, "TokenSale: not started");
8584
require(block.timestamp <= saleStart + saleDuration, "TokenSale: already ended");
86-
require(
87-
_tokenOutAmount <= whitelistedBuyersAmount[msg.sender],
88-
"TokenSale: cannot buy more than allowed"
89-
);
90-
91-
unchecked {
92-
// this subtraction does not underflow due to the check above
93-
whitelistedBuyersAmount[msg.sender] -= _tokenOutAmount;
94-
}
95-
85+
uint256 _tokenOutAmount = whitelistedBuyersAmount[msg.sender];
86+
require(_tokenOutAmount > 0, "TokenSale: non-whitelisted purchaser or have already bought");
87+
whitelistedBuyersAmount[msg.sender] = 0;
9688
tokenInAmount_ = (_tokenOutAmount * tokenOutPrice) / 1e18;
9789
require(
9890
tokenIn.transferFrom(msg.sender, saleRecipient, tokenInAmount_),

test/TokenSale.spec.ts

Lines changed: 14 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -164,32 +164,27 @@ describe('TokenSale', async () => {
164164

165165
it('should revert if trying to buy before sale', async () => {
166166
await setNextBlockTimeStamp(SALE_START - 1);
167-
await expect(tokenSale.connect(buyer1).buy(`1`)).to.be.revertedWith('TokenSale: not started');
167+
await expect(tokenSale.connect(buyer1).buy()).to.be.revertedWith('TokenSale: not started');
168168
});
169169

170170
it('should revert if trying to buy after sale duration', async () => {
171171
await setNextBlockTimeStamp(SALE_START + SALE_DURATION + 1);
172-
await expect(tokenSale.connect(buyer1).buy(`1`)).to.be.revertedWith('TokenSale: already ended');
172+
await expect(tokenSale.connect(buyer1).buy()).to.be.revertedWith('TokenSale: already ended');
173173
});
174174

175175
it('should revert if non-whitelisted tries to buy', async () => {
176-
await expect(tokenSale.connect(user).buy(`1`)).to.be.revertedWith('TokenSale: cannot buy more than allowed');
177-
await expect(tokenSale.connect(other).buy(`1`)).to.be.revertedWith('TokenSale: cannot buy more than allowed');
178-
});
179-
180-
it('should revert if whitelisted tries to buy more than allotted', async () => {
181-
await expect(tokenSale.connect(buyer1).buy(WHITELISTED_AMOUNTS[0].add(`1`))).to.be.revertedWith(
182-
'TokenSale: cannot buy more than allowed'
176+
await expect(tokenSale.connect(user).buy()).to.be.revertedWith(
177+
'TokenSale: non-whitelisted purchaser or have already bought'
183178
);
184-
await expect(tokenSale.connect(buyer2).buy(WHITELISTED_AMOUNTS[1].add(`1`))).to.be.revertedWith(
185-
'TokenSale: cannot buy more than allowed'
179+
await expect(tokenSale.connect(other).buy()).to.be.revertedWith(
180+
'TokenSale: non-whitelisted purchaser or have already bought'
186181
);
187182
});
188183

189-
it('should let whitelisted buy full amount', async () => {
184+
it('should let whitelisted buy only full amount', async () => {
190185
let preBuyerTokenInBalance = await tokenIn.balanceOf(buyer1.address);
191186
let preSellerTokenInBalance = await tokenIn.balanceOf(saleRecipient.address);
192-
await tokenSale.connect(buyer1).buy(WHITELISTED_AMOUNTS[0]);
187+
await tokenSale.connect(buyer1).buy();
193188
let postBuyerTokenInBalance = await tokenIn.balanceOf(buyer1.address);
194189
let tokenInPaid = preBuyerTokenInBalance.sub(postBuyerTokenInBalance);
195190

@@ -208,45 +203,15 @@ describe('TokenSale', async () => {
208203
expect(vesting.unlockEnd).to.eq(SALE_START + ONE_DAY);
209204
expect(vesting.lockedAmounts).to.eq(WHITELISTED_AMOUNTS[0].mul(4).div(5));
210205

211-
// whitelisted cannot buy more
212-
await expect(tokenSale.connect(buyer1).buy(WHITELISTED_AMOUNTS[0].add(`1`))).to.be.revertedWith(
213-
'TokenSale: cannot buy more than allowed'
206+
// whitelisted cannot buy again
207+
await expect(tokenSale.connect(buyer1).buy()).to.be.revertedWith(
208+
'TokenSale: non-whitelisted purchaser or have already bought'
214209
);
215210
});
216211

217-
it('should let whitelisted buy partial amounts several times', async () => {
218-
let preBuyerTokenInBalance = await tokenIn.balanceOf(buyer1.address);
219-
let preSellerTokenInBalance = await tokenIn.balanceOf(saleRecipient.address);
220-
await tokenSale.connect(buyer1).buy(WHITELISTED_AMOUNTS[0].div(4));
221-
await setNextBlockTimeStamp(SALE_START + ONE_DAY);
222-
await tokenSale.connect(buyer1).buy(WHITELISTED_AMOUNTS[0].div(4));
223-
await setNextBlockTimeStamp(SALE_START + 2 * ONE_DAY);
224-
await tokenSale.connect(buyer1).buy(WHITELISTED_AMOUNTS[0].div(4));
225-
await setNextBlockTimeStamp(SALE_START + 3 * ONE_DAY);
226-
await tokenSale.connect(buyer1).buy(WHITELISTED_AMOUNTS[0].div(4));
227-
let postBuyerTokenInBalance = await tokenIn.balanceOf(buyer1.address);
228-
let tokenInPaid = preBuyerTokenInBalance.sub(postBuyerTokenInBalance);
229-
230-
// 0.05 USDC per ARENA => buying 1000.0 ARENA should cost 0.05 USDC / ARENA * 1000.0 ARENA = 50.0 USDC
231-
let expectedTokenIn = ethers.utils.parseUnits(`50`, TOKEN_IN_DECIMALS);
232-
expect(tokenInPaid).eq(expectedTokenIn);
233-
234-
// saleRecipient received entire amount
235-
expect(await tokenIn.balanceOf(saleRecipient.address)).to.eq(preSellerTokenInBalance.add(tokenInPaid));
236-
237-
// buyer received 20% immediately, 80% locked
238-
expect(await tokenOut.balanceOf(buyer1.address)).to.eq(WHITELISTED_AMOUNTS[0].div(5));
239-
const vesting = await tokenLock.vesting(buyer1.address);
240-
let expectedVestingStart = SALE_START + 3 * ONE_DAY;
241-
expect(vesting.unlockBegin).to.eq(expectedVestingStart);
242-
expect(vesting.unlockCliff).to.eq(expectedVestingStart);
243-
expect(vesting.unlockEnd).to.eq(expectedVestingStart + ONE_DAY);
244-
expect(vesting.lockedAmounts).to.eq(WHITELISTED_AMOUNTS[0].mul(4).div(5));
245-
246-
// whitelisted cannot buy more
247-
await expect(tokenSale.connect(buyer1).buy(WHITELISTED_AMOUNTS[0].add(`1`))).to.be.revertedWith(
248-
'TokenSale: cannot buy more than allowed'
249-
);
212+
it('should revert if buyer has insufficient funds', async () => {
213+
await tokenIn.connect(buyer1).transfer(buyer2.address, await tokenIn.balanceOf(buyer1.address));
214+
await expect(tokenSale.connect(buyer1).buy()).to.be.revertedWith('ERC20: transfer amount exceeds balance');
250215
});
251216
});
252217

0 commit comments

Comments
 (0)