Skip to content

Commit

Permalink
wip tests 1155 roles registry
Browse files Browse the repository at this point in the history
  • Loading branch information
ernanirst committed Nov 11, 2023
1 parent 6206935 commit dd37dcf
Show file tree
Hide file tree
Showing 6 changed files with 186 additions and 105 deletions.
23 changes: 13 additions & 10 deletions contracts/RolesRegistry/SftRolesRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,14 @@ contract SftRolesRegistry is IERCXXXX, ERC1155Holder {
}

modifier onlyOwnerOrApprovedWithBalance(address _account, address _tokenAddress, uint256 _tokenId, uint256 _tokenAmount) {
require(_tokenAmount > 0, "SftRolesRegistry: tokenAmount must be greater than zero");
require(
(_account == msg.sender || IERC1155(_tokenAddress).isApprovedForAll(_account, msg.sender)) &&
IERC1155(_tokenAddress).balanceOf(_account, _tokenId) >= _tokenAmount,
"SftRolesRegistry: account not approved or has insufficient balance"
_account == msg.sender || IERC1155(_tokenAddress).isApprovedForAll(_account, msg.sender),
"SftRolesRegistry: account not approved"
);
require(
IERC1155(_tokenAddress).balanceOf(_account, _tokenId) >= _tokenAmount,
"SftRolesRegistry: account has insufficient balance"
);
_;
}
Expand All @@ -40,14 +44,14 @@ contract SftRolesRegistry is IERCXXXX, ERC1155Holder {
external
override
validExpirationDate(_roleAssignment.expirationDate)
onlyOwnerOrApprovedWithBalance(
_roleAssignment.grantor,
_roleAssignment.tokenAddress,
_roleAssignment.tokenId,
_roleAssignment.tokenAmount
)
{

require(
_roleAssignment.grantor == msg.sender ||
IERC1155(_roleAssignment.tokenAddress).isApprovedForAll(_roleAssignment.grantor, msg.sender),
"SftRolesRegistry: account not approved"
);

bytes32 hash = _hashRoleData(
_roleAssignment.nonce,
_roleAssignment.role,
Expand Down Expand Up @@ -95,7 +99,6 @@ contract SftRolesRegistry is IERCXXXX, ERC1155Holder {

// insert on the list
_insert(hash, rootKey, _roleAssignment);

}

function _insert(bytes32 _hash, bytes32 _rootKey, RoleAssignment calldata _roleAssignment) internal {
Expand Down
4 changes: 2 additions & 2 deletions test/LinkedLists.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ import { ethers } from 'hardhat'
import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'
import { expect } from 'chai'
import { beforeEach } from 'mocha'
import { generateRandomInt, assertListItem, assertList, printList } from './helpers'
import { generateRandomInt, assertListItem, assertList } from './helpers'

const { HashZero } = ethers.constants
const HashOne = ethers.utils.formatBytes32String("1")
const HashTwo = ethers.utils.formatBytes32String("2")

describe.only('LinkedLists', async () => {
describe('LinkedLists', async () => {
let LinkedLists: Contract

async function deployContracts() {
Expand Down
93 changes: 0 additions & 93 deletions test/RolesRegistry1155.spec.ts

This file was deleted.

107 changes: 107 additions & 0 deletions test/SftRolesRegistry/SftRolesRegistry.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import { ethers } from 'hardhat'
import { Contract } from 'ethers'
import { beforeEach } from 'mocha'
import { expect } from 'chai'
import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'
import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'
import { buildRoleAssignment, currentUnixTimestamp, ONE_DAY } from './helpers'

// grantRoleFrom
// when nonce does not exist
// should revert if grantor does not have enough tokens
// should revert if tokenAmount is zero
// should grant role when grantor is sender and has enough tokens
// should grant role when sender is approved and grantor has enough tokens
// grant role to two different users and have separate balances
// grant role and wait for it to automatically expire
// when nonce exists
// tbd

describe.only('SftRolesRegistry', async () => {
let SftRolesRegistry: Contract
let MockToken: Contract
let grantor: SignerWithAddress

async function deployContracts() {
const SftRolesRegistryFactory = await ethers.getContractFactory('SftRolesRegistry')
SftRolesRegistry = await SftRolesRegistryFactory.deploy()
const MockTokenFactory = await ethers.getContractFactory('MockERC1155')
MockToken = await MockTokenFactory.deploy()
const signers = await ethers.getSigners()
grantor = signers[0]
return { SftRolesRegistry, MockToken, signers }
}

beforeEach(async () => {
await loadFixture(deployContracts)
})

describe('grantRole', async () => {

it('should revert without a reason if tokenAddress is not an ERC-1155 contract', async () => {
const roleAssignment = buildRoleAssignment()
await expect(SftRolesRegistry.connect(grantor).grantRoleFrom(roleAssignment)).to.be.reverted
})

it('should revert if expirationDate is in the past', async () => {
const roleAssignment = buildRoleAssignment({
expirationDate: currentUnixTimestamp() - ONE_DAY,
})
await expect(SftRolesRegistry.grantRoleFrom(roleAssignment))
.to.be.revertedWith('SftRolesRegistry: expiration date must be in the future')
})

it('should revert when sender is not grantor or approved', async () => {
const roleAssignment = buildRoleAssignment({
tokenAddress: MockToken.address,
})
await expect(SftRolesRegistry.connect(grantor).grantRoleFrom(roleAssignment))
.to.be.revertedWith('SftRolesRegistry: account not approved')
})

it('should revert if contract cannot transfer tokens', async () => {
const roleAssignment = buildRoleAssignment({
tokenAddress: MockToken.address, grantor: grantor.address,
})
await MockToken.mint(grantor.address, roleAssignment.tokenId, roleAssignment.tokenAmount)
await expect(SftRolesRegistry.connect(grantor).grantRoleFrom(roleAssignment))
.to.be.revertedWith('ERC1155: caller is not token owner or approved')
})



it('should revert if tokenAmount is zero', async () => {
const roleAssignment = buildRoleAssignment({
tokenAmount: 0
})
await expect(SftRolesRegistry.connect(grantor).grantRoleFrom(roleAssignment))
.to.be.revertedWith('SftRolesRegistry: tokenAmount must be greater than zero')
})

it('should revert when grantor does not have enough tokens', async () => {
const roleAssignment = buildRoleAssignment({
tokenAddress: MockToken.address, grantor: grantor.address, tokenAmount: 100,
})
await MockToken.mint(grantor.address, roleAssignment.tokenId, roleAssignment.tokenAmount - 10)
await MockToken.connect(grantor).setApprovalForAll(SftRolesRegistry.address, true)
await expect(SftRolesRegistry.connect(grantor).grantRoleFrom(roleAssignment))
.to.be.revertedWith('SftRolesRegistry: account has insufficient balance')
})

// todo tbd
it('should revert if nonce is zero', async () => {
const roleAssignment = buildRoleAssignment({
nonce: 0, tokenAddress: MockToken.address, grantor: grantor.address,
})
await MockToken.mint(grantor.address, roleAssignment.tokenId, roleAssignment.tokenAmount)
await MockToken.connect(grantor).setApprovalForAll(SftRolesRegistry.address, true)
await expect(SftRolesRegistry.connect(grantor).grantRoleFrom(roleAssignment))
.to.be.revertedWith('LinkedLists: invalid nonce')
expect(await MockToken.balanceOf(grantor.address, roleAssignment.tokenId))
.to.be.equal(roleAssignment.tokenAmount)
})


})

})
52 changes: 52 additions & 0 deletions test/SftRolesRegistry/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { solidityKeccak256 } from 'ethers/lib/utils'
import { RoleAssignment } from './types'
import { generateRandomInt } from '../helpers'
import { ethers } from 'hardhat'

const { HashZero, AddressZero } = ethers.constants
export const ONE_DAY = 60 * 60 * 24

export function buildRoleAssignment(
{
// default values
nonce = generateRandomInt(),
role = 'Role()',
tokenAddress = AddressZero,
tokenId = generateRandomInt(),
tokenAmount = generateRandomInt(),
grantor = AddressZero,
grantee = AddressZero,
expirationDate = currentUnixTimestamp() + ONE_DAY,
revocable = true,
data = HashZero,
}: {
// types
nonce?: number,
role?: string,
tokenAddress?: string,
tokenId?: number,
tokenAmount?: number,
grantor?: string,
grantee?: string,
expirationDate?: number,
revocable?: boolean,
data?: string,
} = {}
): RoleAssignment {
return {
nonce,
role: solidityKeccak256(['string'], [role]),
tokenAddress,
tokenId,
tokenAmount,
grantor,
grantee,
expirationDate,
revocable,
data,
}
}

export function currentUnixTimestamp() {
return Math.floor(Date.now() / 1000)
}
12 changes: 12 additions & 0 deletions test/SftRolesRegistry/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export interface RoleAssignment {
nonce: number
role: string
tokenAddress: string
tokenId: number
tokenAmount: number
grantor: string
grantee: string
expirationDate: number
revocable: boolean
data: string
}

0 comments on commit dd37dcf

Please sign in to comment.