diff --git a/packages/contracts/src/OverTheCounter.sol b/packages/contracts/src/OverTheCounter.sol new file mode 100644 index 0000000..936f792 --- /dev/null +++ b/packages/contracts/src/OverTheCounter.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.20; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/utils/Pausable.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; + +contract OverTheCounter is Pausable, AccessControl { + bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); + IERC20 public immutable token; + + event Deposited(address indexed account, uint256 value); + event Withdrawn(address indexed reciever, uint256 amount); + + constructor(IERC20 _token, address _admin) { + token = _token; + _grantRole(DEFAULT_ADMIN_ROLE, _admin); + _grantRole(PAUSER_ROLE, _admin); + } + + function deposit(uint256 amount) external whenNotPaused { + token.transferFrom(msg.sender, address(this), amount); + + emit Deposited(msg.sender, amount); + } + + function withdraw(address receiver, uint256 amount) external onlyRole(DEFAULT_ADMIN_ROLE) { + token.transfer(receiver, amount); + + emit Withdrawn(receiver, amount); + } +} \ No newline at end of file diff --git a/packages/contracts/test/OverTheCounter.t.sol b/packages/contracts/test/OverTheCounter.t.sol new file mode 100644 index 0000000..704514e --- /dev/null +++ b/packages/contracts/test/OverTheCounter.t.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.20; + +import "../src/OverTheCounter.sol"; +import "./BaseTest.sol"; + +contract OverTheCounterTest is BaseTest { + OverTheCounter otc; + SQD token; + + function setUp() public { + (SQD _token,) = deployAll(); + + token = _token; + otc = new OverTheCounter(token, address(this)); + + token.transfer(address(1), 1000); + + token.approve(address(otc), type(uint256).max); + hoax(address(1)); + token.approve(address(otc), type(uint256).max); + } + + function test_Deposit() public { + hoax(address(1)); + otc.deposit(100); + assertEq(token.balanceOf(address(otc)), 100); + } + + function test_Withdraw() public { + otc.deposit(100); + otc.withdraw(address(2), 10); + assertEq(token.balanceOf(address(2)), 10); + } + + function test_RevertsIf_WithdrawNotByAdmin() public { + hoax(address(1)); + expectNotAdminRevert(); + otc.withdraw(address(2), 10); + } +}