Skip to content

Commit

Permalink
Predefined lock size, emit event on lock
Browse files Browse the repository at this point in the history
  • Loading branch information
kanshi committed Jan 26, 2024
1 parent fcb42e6 commit 99c6c42
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 53 deletions.
30 changes: 23 additions & 7 deletions contracts/Registrator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ contract Registrator is Initializable, PausableUpgradeable, AccessControlUpgrade
bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE");

uint256 public lockBlocks;
uint256 public currentLockSize;

IERC20 public tokenContract;

Expand All @@ -27,20 +28,24 @@ contract Registrator is Initializable, PausableUpgradeable, AccessControlUpgrade
mapping(address => LockData) locks;
mapping(address => uint256) public penalties;

event LockRegistered(address indexed _account);

function getLock(address _address) public view returns (LockData memory) {
return locks[_address];
}

function lock(uint256 _amount) external whenNotPaused {
require(tokenContract.transferFrom(msg.sender, address(this), _amount));
locks[msg.sender].amount.push(_amount);
function lock() external whenNotPaused {
require(tokenContract.transferFrom(msg.sender, address(this), currentLockSize));
locks[msg.sender].amount.push(currentLockSize);
locks[msg.sender].unlockAt.push(block.number + lockBlocks);
emit LockRegistered(msg.sender);
}

function lockFor(address _address, uint256 _amount) external whenNotPaused {
require(tokenContract.transferFrom(msg.sender, address(this), _amount));
locks[_address].amount.push(_amount);
function lockFor(address _address) external whenNotPaused {
require(tokenContract.transferFrom(msg.sender, address(this), currentLockSize));
locks[_address].amount.push(currentLockSize);
locks[_address].unlockAt.push(block.number + lockBlocks);
emit LockRegistered(_address);
}

function unlock(uint256 _upto) external whenNotPaused {
Expand Down Expand Up @@ -99,6 +104,15 @@ contract Registrator is Initializable, PausableUpgradeable, AccessControlUpgrade
penalties[_account] = _value;
}

function setLockSize(uint256 _value)
external
whenNotPaused
onlyRole(OPERATOR_ROLE)
{
require(_value > 0, "Lock size has to be non-zero");
currentLockSize = _value;
}


function setLockBlocks(uint256 _value)
external
Expand All @@ -117,11 +131,13 @@ contract Registrator is Initializable, PausableUpgradeable, AccessControlUpgrade
function initialize(
address _tokenAddress,
address payable _operator,
uint256 _lockBlocks
uint256 _lockBlocks,
uint256 _lockSize
) initializer public {
tokenContract = IERC20(_tokenAddress);

lockBlocks = _lockBlocks;
currentLockSize = _lockSize;

__Pausable_init();
__AccessControl_init();
Expand Down
2 changes: 1 addition & 1 deletion operations/registrator-deploy-dev-goerli.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ job "registrator-deploy-dev-goerli" {

config {
network_mode = "host"
image = "ghcr.io/ator-development/registrator:0.1.0"
image = "ghcr.io/ator-development/registrator:0.1.1"
entrypoint = ["npx"]
command = "hardhat"
args = ["run", "--network", "goerli", "scripts/deploy.ts"]
Expand Down
2 changes: 1 addition & 1 deletion operations/registrator-deploy-live-goerli.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ job "registrator-deploy-live-goerli" {

config {
network_mode = "host"
image = "ghcr.io/ator-development/registrator:0.1.0"
image = "ghcr.io/ator-development/registrator:0.1.1"
entrypoint = ["npx"]
command = "hardhat"
args = ["run", "--network", "goerli", "scripts/deploy.ts"]
Expand Down
2 changes: 1 addition & 1 deletion operations/registrator-deploy-stage-goerli.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ job "registrator-deploy-stage-goerli" {

config {
network_mode = "host"
image = "ghcr.io/ator-development/registrator:0.1.0"
image = "ghcr.io/ator-development/registrator:0.1.1"
entrypoint = ["npx"]
command = "hardhat"
args = ["run", "--network", "goerli", "scripts/deploy.ts"]
Expand Down
2 changes: 1 addition & 1 deletion operations/registrator-operator-scripts-dev-goerli.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ job "registrator-operator-scripts-dev-goerli" {

config {
network_mode = "host"
image = "ghcr.io/ator-development/registrator:0.4.17"
image = "ghcr.io/ator-development/registrator:0.1.1"
entrypoint = ["npx"]
command = "hardhat"
args = ["run", "--network", "goerli", "scripts/operator-scripts.ts"]
Expand Down
90 changes: 48 additions & 42 deletions test/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'
describe("Registrator contract", function () {

const defaultLockBlocks = 10n;
const defaultLockSize = 100n * BigInt(1e18);

async function deploy() {
const Token = await ethers.getContractFactory('Token')
Expand All @@ -16,7 +17,7 @@ describe("Registrator contract", function () {

const registrator = await upgrades.deployProxy(
Registrator,
[ tokenAddress, operator.address, defaultLockBlocks ]
[ tokenAddress, operator.address, defaultLockBlocks, defaultLockSize ]
)
await registrator.waitForDeployment()
const registratorAddress = await registrator.getAddress()
Expand Down Expand Up @@ -50,7 +51,7 @@ describe("Registrator contract", function () {
// @ts-ignore
await token.connect(tester).approve(registratorAddress, lockAmount)
// @ts-ignore
const result = await registrator.connect(tester).lock(lockAmount)
const result = await registrator.connect(tester).lock()

expect(await token.balanceOf(registratorAddress)).to.equal(lockAmount)
expect(await token.balanceOf(tester.address)).to.equal(lockAmount)
Expand All @@ -63,14 +64,14 @@ describe("Registrator contract", function () {
const { admin, registrator, tester, token, registratorAddress, receiver } =
await loadFixture(deploy)

const lockAmount = 100n * BigInt(1e18)
const lockAmount = defaultLockSize

// @ts-ignore
await token.connect(admin).transfer(tester.address, 2n * lockAmount)
// @ts-ignore
await token.connect(tester).approve(registratorAddress, lockAmount)
// @ts-ignore
const result = await registrator.connect(tester).lockFor(receiver.address, lockAmount)
const result = await registrator.connect(tester).lockFor(receiver.address)

expect(await token.balanceOf(registratorAddress)).to.equal(lockAmount)
expect(await token.balanceOf(tester.address)).to.equal(lockAmount)
Expand All @@ -90,18 +91,29 @@ describe("Registrator contract", function () {
expect(await registrator.lockBlocks()).to.equal(defaultLockBlocks * 2n)
})

it('Allows setting only non-zero lock size', async () => {
const { registrator, operator } = await loadFixture(deploy)

expect(await registrator.currentLockSize()).to.equal(defaultLockSize)
// @ts-ignore
await expect(registrator.connect(operator).setLockSize(0)).to.be.revertedWith(`Lock size has to be non-zero`)
// @ts-ignore
await registrator.connect(operator).setLockSize(defaultLockSize * 2n)
expect(await registrator.currentLockSize()).to.equal(defaultLockSize * 2n)
})

it('Block unlocking tokens before unlock height', async () => {
const { admin, registrator, tester, token, registratorAddress } =
await loadFixture(deploy)

const lockAmount = 100n * BigInt(1e18)
const lockAmount = defaultLockSize

// @ts-ignore
await token.connect(admin).transfer(tester.address, 2n * lockAmount)
// @ts-ignore
await token.connect(tester).approve(registratorAddress, lockAmount)
// @ts-ignore
const result = await registrator.connect(tester).lock(lockAmount)
const result = await registrator.connect(tester).lock()

const data = await registrator.getLock(tester.address)
expect(data[0][0]).to.equal(lockAmount)
Expand All @@ -115,14 +127,14 @@ describe("Registrator contract", function () {
const { admin, registrator, tester, token, registratorAddress } =
await loadFixture(deploy)

const lockAmount = 100n * BigInt(1e18)
const lockAmount = defaultLockSize

// @ts-ignore
await token.connect(admin).transfer(tester.address, lockAmount)
// @ts-ignore
await token.connect(tester).approve(registratorAddress, lockAmount)
// @ts-ignore
const result = await registrator.connect(tester).lock(lockAmount)
const result = await registrator.connect(tester).lock()
expect(await token.balanceOf(tester.address)).to.equal(0)

for (let i = 0; i < defaultLockBlocks; i++) {
Expand All @@ -138,99 +150,93 @@ describe("Registrator contract", function () {
const { admin, registrator, tester, token, registratorAddress, operator } =
await loadFixture(deploy)

const lockAmount1 = 1n * BigInt(1e18)
const lockAmount2 = 10n * BigInt(1e18)
const lockAmount3 = 100n * BigInt(1e18)
const lockAmount4 = 1000n * BigInt(1e18)
const lockAmount5 = 10000n * BigInt(1e18)
const lockAmount = defaultLockSize

// @ts-ignore
await token.connect(admin).transfer(tester.address, lockAmount1 + lockAmount2 + lockAmount3 + lockAmount4 + lockAmount5)
await token.connect(admin).transfer(tester.address, lockAmount * 5n)

// @ts-ignore
await token.connect(tester).approve(registratorAddress, lockAmount1)
await token.connect(tester).approve(registratorAddress, lockAmount)
// @ts-ignore
await registrator.connect(tester).lock(lockAmount1)
await registrator.connect(tester).lock()
// @ts-ignore
await registrator.connect(operator).setLockBlocks(defaultLockBlocks * 2n)
// @ts-ignore
await token.connect(tester).approve(registratorAddress, lockAmount2)
await token.connect(tester).approve(registratorAddress, lockAmount)
// @ts-ignore
await registrator.connect(tester).lock(lockAmount2)
await registrator.connect(tester).lock()
// @ts-ignore
await registrator.connect(operator).setLockBlocks(defaultLockBlocks * 3n)
// @ts-ignore
await token.connect(tester).approve(registratorAddress, lockAmount3)
await token.connect(tester).approve(registratorAddress, lockAmount)
// @ts-ignore
await registrator.connect(tester).lock(lockAmount3)
await registrator.connect(tester).lock()
// @ts-ignore
await registrator.connect(operator).setLockBlocks(defaultLockBlocks * 4n)
// @ts-ignore
await token.connect(tester).approve(registratorAddress, lockAmount4)
await token.connect(tester).approve(registratorAddress, lockAmount)
// @ts-ignore
await registrator.connect(tester).lock(lockAmount4)
await registrator.connect(tester).lock()
// @ts-ignore
await registrator.connect(operator).setLockBlocks(defaultLockBlocks * 5n)
// @ts-ignore
await token.connect(tester).approve(registratorAddress, lockAmount5)
await token.connect(tester).approve(registratorAddress, lockAmount)
// @ts-ignore
await registrator.connect(tester).lock(lockAmount5)
await registrator.connect(tester).lock()


for (let i = 0; i < defaultLockBlocks * 3n; i++) {
await network.provider.send("evm_mine")
}

// @ts-ignore
await registrator.connect(tester).unlock(lockAmount5)
await registrator.connect(tester).unlock(lockAmount * 5n)

expect(await token.balanceOf(tester.address)).to.equal(lockAmount1 + lockAmount2 + lockAmount3)
expect(await token.balanceOf(tester.address)).to.equal(lockAmount * 3n)

const data = await registrator.getLock(tester.address)

expect(data[0][0]).to.equal(lockAmount4)
expect(data[0][0]).to.equal(lockAmount)
})

it('Unlocks partial amount of tokens among multiple locks', async () => {
const { admin, registrator, tester, token, registratorAddress, operator } =
await loadFixture(deploy)

const lockAmount1 = 1n * BigInt(1e18)
const lockAmount2 = 10n * BigInt(1e18)
const lockAmount3 = 100n * BigInt(1e18)
const lockAmount = defaultLockSize

// @ts-ignore
await token.connect(admin).transfer(tester.address, lockAmount1 + lockAmount2 + lockAmount3)
await token.connect(admin).transfer(tester.address, lockAmount * 3n)

// @ts-ignore
await token.connect(tester).approve(registratorAddress, lockAmount1)
await token.connect(tester).approve(registratorAddress, lockAmount)
// @ts-ignore
await registrator.connect(tester).lock(lockAmount1)
await registrator.connect(tester).lock()
// @ts-ignore
await registrator.connect(operator).setLockBlocks(defaultLockBlocks * 2n)
// @ts-ignore
await token.connect(tester).approve(registratorAddress, lockAmount2)
await token.connect(tester).approve(registratorAddress, lockAmount)
// @ts-ignore
await registrator.connect(tester).lock(lockAmount2)
await registrator.connect(tester).lock()
// @ts-ignore
await registrator.connect(operator).setLockBlocks(defaultLockBlocks * 3n)
// @ts-ignore
await token.connect(tester).approve(registratorAddress, lockAmount3)
await token.connect(tester).approve(registratorAddress, lockAmount)
// @ts-ignore
await registrator.connect(tester).lock(lockAmount3)
await registrator.connect(tester).lock()

for (let i = 0; i < defaultLockBlocks * 2n; i++) {
await network.provider.send("evm_mine")
}

// @ts-ignore
await registrator.connect(tester).unlock(lockAmount1 + (lockAmount2 / 2n))
await registrator.connect(tester).unlock(lockAmount + (lockAmount / 2n))

expect(await token.balanceOf(tester.address)).to.equal(lockAmount1 + (lockAmount2 / 2n))
expect(await token.balanceOf(tester.address)).to.equal(lockAmount + (lockAmount / 2n))

const data = await registrator.getLock(tester.address)

expect(data[0][0]).to.equal(lockAmount2 / 2n)
expect(data[0][0]).to.equal(lockAmount / 2n)
})

it('Allows setting penalties per address', async () => {
Expand All @@ -254,15 +260,15 @@ describe("Registrator contract", function () {
const preData = await registrator.getLock(tester.address)
expect(preData[0].length).to.equal(0)

const lockAmount = 1n * BigInt(1e18)
const lockAmount = defaultLockSize

// @ts-ignore
await token.connect(admin).transfer(tester.address, lockAmount)

// @ts-ignore
await token.connect(tester).approve(registratorAddress, lockAmount)
// @ts-ignore
await registrator.connect(tester).lock(lockAmount)
await registrator.connect(tester).lock()

for (let i = 0; i < defaultLockBlocks; i++) {
await network.provider.send("evm_mine")
Expand Down

0 comments on commit 99c6c42

Please sign in to comment.