diff --git a/contracts/DispenserProvider.sol b/contracts/DispenserProvider.sol index 8193dbe..fdc2ca6 100644 --- a/contracts/DispenserProvider.sol +++ b/contracts/DispenserProvider.sol @@ -3,64 +3,44 @@ pragma solidity ^0.8.0; import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import "@openzeppelin/contracts/interfaces/IERC20.sol"; -import "./DispenserView.sol"; +import "@poolzfinance/lockdeal-nft/contracts/SimpleProviders/DealProvider/DealProvider.sol"; +import "./DispenserState.sol"; -contract DispenserProvider is DispenserView { +contract DispenserProvider is DealProvider, DispenserState { using ECDSA for bytes32; - constructor(ILockDealNFT _lockDealNFT) { - require( - address(_lockDealNFT) != address(0), - "DispenserProvider: Invalid lockDealNFT address" - ); + constructor(ILockDealNFT _lockDealNFT) DealProvider(_lockDealNFT) { name = "DispenserProvider"; - lockDealNFT = _lockDealNFT; } - function deposit( - address signer, - IERC20 tokenAddress, - uint256 amount, - bytes calldata data - ) external returns (uint256 poolId) { - require( - signer != address(0), - "DispenserProvider: Invalid signer address" - ); - require( - address(tokenAddress) != address(0), - "DispenserProvider: Invalid token address" - ); - require(amount > 0, "DispenserProvider: Invalid amount"); - poolId = lockDealNFT.safeMintAndTransfer( - signer, - address(tokenAddress), - msg.sender, - amount, - this, - data - ); - uint256[] memory params = new uint256[](1); - params[0] = amount; - _registerPool(poolId, params); - } - - function registerPool( - uint256 poolId, - uint256[] calldata params + /** + * @dev Creates a new pool with the specified parameters. + * @param addresses[0] The address of the signer. + * @param addresses[1] The address of the token associated with the pool. + * @param params An array of pool parameters [poolIdToAmount]. + * @param signature The signature of the pool owner. + * @return poolId The ID of the newly created pool. + */ + function createNewPool( + address[] calldata addresses, + uint256[] calldata params, + bytes calldata signature ) external - onlyProvider - validProviderId(poolId) + virtual + override + firewallProtected + validAddressesLength(addresses.length, 2) validParamsLength(params.length, currentParamsTargetLength()) + returns (uint256 poolId) { + require(addresses[0] != address(0), "DispenserProvider: Invalid signer address"); + require(address(addresses[1]) != address(0), "DispenserProvider: Invalid token address"); + require(params[0] > 0, "DispenserProvider: Invalid amount"); + poolId = lockDealNFT.safeMintAndTransfer(addresses[0], address(addresses[1]), msg.sender, params[0], this,signature); _registerPool(poolId, params); } - function _registerPool(uint256 poolId, uint256[] memory params) internal { - leftAmount[poolId] = params[0]; - } - function createLock( uint256 poolId, uint256 validUntil, @@ -111,7 +91,7 @@ contract DispenserProvider is DispenserView { uint256 poolId = lockDealNFT.mintForProvider(owner, data[i].simpleProvider); data[i].simpleProvider.registerPool(poolId, data[i].params); lockDealNFT.cloneVaultId(poolId, tokenPoolId); - leftAmount[tokenPoolId] -= data[i].params[0]; + poolIdToAmount[tokenPoolId] -= data[i].params[0]; _withdrawIfAvailable(data[i].simpleProvider, poolId, owner); } } @@ -136,12 +116,4 @@ contract DispenserProvider is DispenserView { address recoveredSigner = hash.recover(signature); success = recoveredSigner == signer; } - - function withdraw(uint256) external pure override returns (uint256, bool) { - require(false, "DispenserProvider: Not implemented yet"); - } - - function split(uint256, uint256, uint256) external pure override { - require(false, "DispenserProvider: Not implemented yet"); - } } diff --git a/contracts/DispenserState.sol b/contracts/DispenserState.sol index 488ff1d..fdf1912 100644 --- a/contracts/DispenserState.sol +++ b/contracts/DispenserState.sol @@ -7,7 +7,6 @@ import "@poolzfinance/poolz-helper-v2/contracts/interfaces/ISimpleProvider.sol"; contract DispenserState { mapping(uint256 => mapping(address => bool)) public isTaken; - mapping(uint256 => uint256) public leftAmount; struct Builder { ISimpleProvider simpleProvider; diff --git a/contracts/DispenserView.sol b/contracts/DispenserView.sol deleted file mode 100644 index 8bdf5d5..0000000 --- a/contracts/DispenserView.sol +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import "./DispenserState.sol"; -import "@poolzfinance/lockdeal-nft/contracts/SimpleProviders/Provider/ProviderModifiers.sol"; - -abstract contract DispenserView is DispenserState, ProviderModifiers { - function getParams(uint256 poolId) external override view returns (uint256[] memory params) { - params = new uint256[](1); - params[0] = leftAmount[poolId]; - } - - function getWithdrawableAmount(uint256 poolId) external override view returns (uint256 amount) { - amount = leftAmount[poolId]; - } -} diff --git a/test/DispenserProvider.ts b/test/DispenserProvider.ts index 9e8fe35..82a2491 100644 --- a/test/DispenserProvider.ts +++ b/test/DispenserProvider.ts @@ -28,6 +28,8 @@ describe("Dispenser Provider tests", function () { let vaultManager: VaultManager let packedData: string let poolId: number + let addresses: string[] + let params: [BigNumber] let validTime: BigNumber const builderType = ["uint256", "uint256", "address", "tuple(address,uint256[])[]"] const creationSignature: Bytes = ethers.utils.toUtf8Bytes("signature") @@ -58,9 +60,11 @@ describe("Dispenser Provider tests", function () { beforeEach(async () => { const ERC20Token = await ethers.getContractFactory("ERC20Token") token = await ERC20Token.deploy("Test", "TST") + params = [amount] + addresses = [signer.address, token.address] poolId = (await lockDealNFT.totalSupply()).toNumber() await token.approve(vaultManager.address, amount) - await dispenserProvider.connect(owner).deposit(signer.address, token.address, amount, creationSignature) + await dispenserProvider.connect(owner).createNewPool(addresses, params, creationSignature) validTime = ethers.BigNumber.from((await time.latest()) + ONE_DAY) userData = { simpleProvider: lockProvider.address, params: [amount.div(2), validTime] } usersData = [{ simpleProvider: lockProvider.address, params: [amount.div(2), validTime] }] @@ -77,14 +81,14 @@ describe("Dispenser Provider tests", function () { }) it("should increase leftAmount after creation", async () => { - expect(await dispenserProvider.leftAmount(poolId)).to.equal(amount) + expect(await dispenserProvider.poolIdToAmount(poolId)).to.equal(amount) }) it("should deacrease leftAmount after lock", async () => { const signatureData = [poolId, validTime, user.address, userData] const signature = await createSignature(signer, signatureData) await dispenserProvider.connect(user).createLock(poolId, validTime, user.address, usersData, signature) - expect(await dispenserProvider.leftAmount(poolId)).to.equal(amount.div(2)) + expect(await dispenserProvider.poolIdToAmount(poolId)).to.equal(amount.div(2)) }) it("should transfer if available", async () => { @@ -127,8 +131,9 @@ describe("Dispenser Provider tests", function () { }) it("should revert invalid signer address", async () => { + addresses = [constants.AddressZero, token.address] await expect( - dispenserProvider.connect(owner).deposit(constants.AddressZero, token.address, amount, creationSignature) + dispenserProvider.connect(owner).createNewPool(addresses, params, creationSignature) ).to.be.revertedWith("DispenserProvider: Invalid signer address") }) @@ -141,34 +146,16 @@ describe("Dispenser Provider tests", function () { }) it("should revert invalid signer address", async () => { + addresses = [signer.address, constants.AddressZero] await expect( - dispenserProvider.connect(owner).deposit(owner.address, constants.AddressZero, amount, creationSignature) + dispenserProvider.connect(owner).createNewPool(addresses, params, creationSignature) ).to.be.revertedWith("DispenserProvider: Invalid token address") }) it("should revert invalid signer address", async () => { + params = [BigNumber.from(0)] await expect( - dispenserProvider.connect(owner).deposit(owner.address, token.address, 0, creationSignature) + dispenserProvider.connect(owner).createNewPool(addresses, params, creationSignature) ).to.be.revertedWith("DispenserProvider: Invalid amount") }) - - it("should revert split", async () => { - const halfRatio = ethers.utils.parseUnits("1", 21).div(2) - const packedData = ethers.utils.defaultAbiCoder.encode(["uint256", "address"], [halfRatio, owner.address]) - await expect( - lockDealNFT - .connect(signer) - [ - "safeTransferFrom(address,address,uint256,bytes)" - ](signer.address, lockDealNFT.address, poolId, packedData) - ).to.be.revertedWith("DispenserProvider: Not implemented yet") - }) - - it("should revert withdraw", async () => { - await expect( - lockDealNFT - .connect(signer) - ["safeTransferFrom(address,address,uint256)"](signer.address, lockDealNFT.address, poolId) - ).to.be.revertedWith("DispenserProvider: Not implemented yet") - }) })