mirror of
https://github.com/logos-storage/logos-storage-contracts-eth.git
synced 2026-01-07 07:43:08 +00:00
vault: deposit and withdraw
This commit is contained in:
parent
1982e71d52
commit
d8049faf22
34
contracts/Vault.sol
Normal file
34
contracts/Vault.sol
Normal file
@ -0,0 +1,34 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity 0.8.28;
|
||||
|
||||
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
|
||||
|
||||
using SafeERC20 for IERC20;
|
||||
|
||||
contract Vault {
|
||||
IERC20 private immutable _token;
|
||||
mapping(address => mapping(bytes32 => uint256)) private _amounts;
|
||||
|
||||
constructor(IERC20 token) {
|
||||
_token = token;
|
||||
}
|
||||
|
||||
function amount(bytes32 id) public view returns (uint256) {
|
||||
return _amounts[msg.sender][id];
|
||||
}
|
||||
|
||||
function deposit(bytes32 id, address from, uint256 value) public {
|
||||
require(_amounts[msg.sender][id] == 0, DepositAlreadyExists(id));
|
||||
_amounts[msg.sender][id] = value;
|
||||
_token.safeTransferFrom(from, address(this), value);
|
||||
}
|
||||
|
||||
function withdraw(bytes32 id, address recipient) public {
|
||||
uint256 value = _amounts[msg.sender][id];
|
||||
delete _amounts[msg.sender][id];
|
||||
_token.safeTransfer(recipient, value);
|
||||
}
|
||||
|
||||
error DepositAlreadyExists(bytes32 id);
|
||||
}
|
||||
76
test/Vault.tests.js
Normal file
76
test/Vault.tests.js
Normal file
@ -0,0 +1,76 @@
|
||||
const { expect } = require("chai")
|
||||
const { ethers } = require("hardhat")
|
||||
const { randomBytes } = ethers.utils
|
||||
|
||||
describe("Vault", function () {
|
||||
let token
|
||||
let vault
|
||||
let payer
|
||||
let recipient
|
||||
|
||||
beforeEach(async function () {
|
||||
const TestToken = await ethers.getContractFactory("TestToken")
|
||||
token = await TestToken.deploy()
|
||||
const Vault = await ethers.getContractFactory("Vault")
|
||||
vault = await Vault.deploy(token.address)
|
||||
;[_, payer, recipient] = await ethers.getSigners()
|
||||
await token.mint(payer.address, 1_000_000)
|
||||
})
|
||||
|
||||
describe("depositing", function () {
|
||||
const id = randomBytes(32)
|
||||
const amount = 42
|
||||
|
||||
it("accepts deposits of tokens", async function () {
|
||||
await token.connect(payer).approve(vault.address, amount)
|
||||
await vault.deposit(id, payer.address, amount)
|
||||
expect(await vault.amount(id)).to.equal(amount)
|
||||
})
|
||||
|
||||
it("keeps custody of tokens that are deposited", async function () {
|
||||
await token.connect(payer).approve(vault.address, amount)
|
||||
await vault.deposit(id, payer.address, amount)
|
||||
expect(await token.balanceOf(vault.address)).to.equal(amount)
|
||||
})
|
||||
|
||||
it("deposit fails when tokens cannot be transferred", async function () {
|
||||
await token.connect(payer).approve(vault.address, amount - 1)
|
||||
const depositing = vault.deposit(id, payer.address, amount)
|
||||
await expect(depositing).to.be.revertedWith("insufficient allowance")
|
||||
})
|
||||
|
||||
it("requires deposit ids to be unique", async function () {
|
||||
await token.connect(payer).approve(vault.address, 2 * amount)
|
||||
await vault.deposit(id, payer.address, amount)
|
||||
const depositing = vault.deposit(id, payer.address, amount)
|
||||
await expect(depositing).to.be.revertedWith("DepositAlreadyExists")
|
||||
})
|
||||
|
||||
it("separates deposits from different owners", async function () {
|
||||
let [owner1, owner2] = await ethers.getSigners()
|
||||
await token.connect(payer).approve(vault.address, 3)
|
||||
await vault.connect(owner1).deposit(id, payer.address, 1)
|
||||
await vault.connect(owner2).deposit(id, payer.address, 2)
|
||||
expect(await vault.connect(owner1).amount(id)).to.equal(1)
|
||||
expect(await vault.connect(owner2).amount(id)).to.equal(2)
|
||||
})
|
||||
})
|
||||
|
||||
describe("withdrawing", function () {
|
||||
const id = randomBytes(32)
|
||||
|
||||
it("can withdraw a deposit", async function () {
|
||||
const amount = 42
|
||||
await token.connect(payer).approve(vault.address, amount)
|
||||
await vault.deposit(id, payer.address, amount)
|
||||
await vault.withdraw(id, recipient.address)
|
||||
expect(await vault.amount(id)).to.equal(0)
|
||||
expect(await token.balanceOf(recipient.address)).to.equal(amount)
|
||||
})
|
||||
|
||||
it("ignores withdrawal of an empty deposit", async function () {
|
||||
await vault.withdraw(id, recipient.address)
|
||||
expect(await token.balanceOf(recipient.address)).to.equal(0)
|
||||
})
|
||||
})
|
||||
})
|
||||
Loading…
x
Reference in New Issue
Block a user