Skip to content

Commit

Permalink
refactor: NFT fix
Browse files Browse the repository at this point in the history
  • Loading branch information
kupermind committed Oct 23, 2024
1 parent 528f7c1 commit bc9a4e9
Show file tree
Hide file tree
Showing 7 changed files with 273 additions and 112 deletions.
6 changes: 4 additions & 2 deletions contracts/contribute/ContributeManager.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

import {ERC721TokenReceiver} from "../../lib/autonolas-registries/lib/solmate/src/tokens/ERC721.sol";
import {IContributors} from "./interfaces/IContributors.sol";
import {IService} from "./interfaces/IService.sol";
import {IStaking} from "./interfaces/IStaking.sol";
Expand Down Expand Up @@ -50,7 +51,7 @@ error ServiceOwnerOnly(uint256 serviceId, address sender, address serviceOwner);
/// @author Andrey Lebedev - <[email protected]>
/// @author Tatiana Priemova - <[email protected]>
/// @author David Vilela - <[email protected]>
contract ContributeManager {
contract ContributeManager is ERC721TokenReceiver {
event CreatedAndStaked(uint256 indexed socialId, address indexed serviceOwner, uint256 serviceId,
address indexed multisig, address stakingInstance);
event Staked(uint256 indexed socialId, address indexed serviceOwner, uint256 serviceId,
Expand Down Expand Up @@ -225,7 +226,8 @@ contract ContributeManager {
uint256 threshold = IStaking(stakingInstance).threshold();
// Check for number of agent instances that must be equal to one,
// since msg.sender is the only service multisig owner
if (numAgentInstances != NUM_AGENT_INSTANCES || threshold != THRESHOLD) {
if ((numAgentInstances > 0 && numAgentInstances != NUM_AGENT_INSTANCES) ||
(threshold > 0 && threshold != THRESHOLD)) {
revert WrongStakingInstance(stakingInstance);
}

Expand Down
3 changes: 1 addition & 2 deletions contracts/contribute/interfaces/IToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,5 @@ interface IToken {
/// @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
/// @param spender Account address that will be able to transfer tokens on behalf of the caller.
/// @param amount Token amount.
/// @return True if the function execution is successful.
function approve(address spender, uint256 amount) external returns (bool);
function approve(address spender, uint256 amount) external;
}
11 changes: 6 additions & 5 deletions contracts/test/ABICreator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ pragma solidity ^0.8.25;
// Getting ABIs for the Gnosis Safe master copy and proxy contracts
import "@gnosis.pm/safe-contracts/contracts/GnosisSafe.sol";

Check warning on line 5 in contracts/test/ABICreator.sol

View workflow job for this annotation

GitHub Actions / build

global import of path @gnosis.pm/safe-contracts/contracts/GnosisSafe.sol is not allowed. Specify names to import individually or bind all exports of the module into a name (import "path" as Name)
import "@gnosis.pm/safe-contracts/contracts/proxies/GnosisSafeProxyFactory.sol";

Check warning on line 6 in contracts/test/ABICreator.sol

View workflow job for this annotation

GitHub Actions / build

global import of path @gnosis.pm/safe-contracts/contracts/proxies/GnosisSafeProxyFactory.sol is not allowed. Specify names to import individually or bind all exports of the module into a name (import "path" as Name)
import "@gnosis.pm/safe-contracts/contracts/handler/DefaultCallbackHandler.sol";

Check warning on line 7 in contracts/test/ABICreator.sol

View workflow job for this annotation

GitHub Actions / build

global import of path @gnosis.pm/safe-contracts/contracts/handler/DefaultCallbackHandler.sol is not allowed. Specify names to import individually or bind all exports of the module into a name (import "path" as Name)
import "@gnosis.pm/safe-contracts/contracts/libraries/MultiSendCallOnly.sol";

Check warning on line 8 in contracts/test/ABICreator.sol

View workflow job for this annotation

GitHub Actions / build

global import of path @gnosis.pm/safe-contracts/contracts/libraries/MultiSendCallOnly.sol is not allowed. Specify names to import individually or bind all exports of the module into a name (import "path" as Name)

// Getting ABIs for registry contracts
import "../../lib/autonolas-registries/contracts/ComponentRegistry.sol";
import "../../lib/autonolas-registries/contracts/AgentRegistry.sol";
import "../../lib/autonolas-registries/contracts/ServiceRegistry.sol";
import "../../lib/autonolas-registries/contracts/ServiceRegistryTokenUtility.sol";
import "../../lib/autonolas-registries/contracts/multisigs/GnosisSafeMultisig.sol";
import {OperatorWhitelist} from "../../lib/autonolas-registries/contracts/utils/OperatorWhitelist.sol";

Check warning on line 11 in contracts/test/ABICreator.sol

View workflow job for this annotation

GitHub Actions / build

imported name OperatorWhitelist is not used
import {ServiceRegistryL2} from "../../lib/autonolas-registries/contracts/ServiceRegistryL2.sol";

Check warning on line 12 in contracts/test/ABICreator.sol

View workflow job for this annotation

GitHub Actions / build

imported name ServiceRegistryL2 is not used
import {ServiceRegistryTokenUtility} from "../../lib/autonolas-registries/contracts/ServiceRegistryTokenUtility.sol";

Check warning on line 13 in contracts/test/ABICreator.sol

View workflow job for this annotation

GitHub Actions / build

imported name ServiceRegistryTokenUtility is not used
import {ServiceManagerToken} from "../../lib/autonolas-registries/contracts/ServiceManagerToken.sol";

Check warning on line 14 in contracts/test/ABICreator.sol

View workflow job for this annotation

GitHub Actions / build

imported name ServiceManagerToken is not used
import {GnosisSafeMultisig} from "../../lib/autonolas-registries/contracts/multisigs/GnosisSafeMultisig.sol";

Check warning on line 15 in contracts/test/ABICreator.sol

View workflow job for this annotation

GitHub Actions / build

imported name GnosisSafeMultisig is not used
import {StakingFactory} from "../../lib/autonolas-registries/contracts/staking/StakingFactory.sol";

Check warning on line 16 in contracts/test/ABICreator.sol

View workflow job for this annotation

GitHub Actions / build

imported name StakingFactory is not used
import {StakingToken} from "../../lib/autonolas-registries/contracts/staking/StakingToken.sol";
import {StakingNativeToken} from "../../lib/autonolas-registries/contracts/staking/StakingNativeToken.sol";
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"chai": "^4.3.10",
"eslint": "^8.52.0",
"ethers": "^5.7.2",
"hardhat": "^2.22.4",
"hardhat": "^2.22.14",
"hardhat-contract-sizer": "^2.10.0",
"hardhat-deploy": "^0.11.43",
"hardhat-deploy-ethers": "^0.3.0-beta.13",
Expand Down
4 changes: 2 additions & 2 deletions scripts/deployment/deploy_10_contribute_activity_checker.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ async function main() {
const gasPrice = ethers.utils.parseUnits(gasPriceInGwei, "gwei");
const ContributeActivityChecker = await ethers.getContractFactory("ContributeActivityChecker");
console.log("You are signing the following transaction: ContributeActivityChecker.connect(EOA).deploy()");
const contributeActivityChecker = await ContributeActivityChecker.connect(EOA).deploy(contributorsProxyAddress, livenessRatio,
{ gasPrice });
const contributeActivityChecker = await ContributeActivityChecker.connect(EOA).deploy(contributorsProxyAddress,
livenessRatio, { gasPrice });
const result = await contributeActivityChecker.deployed();

// Transaction details
Expand Down
175 changes: 175 additions & 0 deletions test/StakingContribute.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
/*global describe, context, beforeEach, it*/
const { expect } = require("chai");

Check warning on line 2 in test/StakingContribute.js

View workflow job for this annotation

GitHub Actions / build

'expect' is assigned a value but never used
const { ethers } = require("hardhat");
const helpers = require("@nomicfoundation/hardhat-network-helpers");

Check warning on line 4 in test/StakingContribute.js

View workflow job for this annotation

GitHub Actions / build

'helpers' is assigned a value but never used
const safeContracts = require("@gnosis.pm/safe-contracts");

Check warning on line 5 in test/StakingContribute.js

View workflow job for this annotation

GitHub Actions / build

'safeContracts' is assigned a value but never used

describe("Staking", function () {
let componentRegistry;

Check warning on line 8 in test/StakingContribute.js

View workflow job for this annotation

GitHub Actions / build

'componentRegistry' is defined but never used
let agentRegistry;

Check warning on line 9 in test/StakingContribute.js

View workflow job for this annotation

GitHub Actions / build

'agentRegistry' is defined but never used
let serviceRegistry;
let serviceRegistryTokenUtility;
let operatorWhitelist;
let serviceManager;
let token;
let gnosisSafe;
let gnosisSafeProxyFactory;
let fallbackHandler;
let gnosisSafeMultisig;
let stakingFactory;
let contributors;
let contributorsProxy;
let contributeManager;
let contributeActivityChecker;
let stakingTokenImplementation;
let stakingToken;
let signers;
let deployer;
let agentInstances;

Check warning on line 28 in test/StakingContribute.js

View workflow job for this annotation

GitHub Actions / build

'agentInstances' is defined but never used
let bytecodeHash;
const AddressZero = ethers.constants.AddressZero;
const HashZero = ethers.constants.HashZero;
const defaultHash = "0x" + "5".repeat(64);
const regDeposit = 1000;

Check warning on line 33 in test/StakingContribute.js

View workflow job for this annotation

GitHub Actions / build

'regDeposit' is assigned a value but never used
const regBond = 1000;
const serviceId = 1;

Check warning on line 35 in test/StakingContribute.js

View workflow job for this annotation

GitHub Actions / build

'serviceId' is assigned a value but never used
const agentId = 1;
let socialId = 1;
const agentIds = [1];

Check warning on line 38 in test/StakingContribute.js

View workflow job for this annotation

GitHub Actions / build

'agentIds' is assigned a value but never used
const agentParams = [[1, regBond]];

Check warning on line 39 in test/StakingContribute.js

View workflow job for this annotation

GitHub Actions / build

'agentParams' is assigned a value but never used
const threshold = 1;
const livenessPeriod = 10; // Ten seconds
const initSupply = "5" + "0".repeat(26);
const payload = "0x";
const livenessRatio = "1" + "0".repeat(16); // 0.01 transaction per second (TPS)
let serviceParams = {
metadataHash: defaultHash,
maxNumServices: 3,
rewardsPerSecond: "1" + "0".repeat(15),
minStakingDeposit: 10,
minNumStakingPeriods: 3,
maxNumInactivityPeriods: 3,
livenessPeriod: livenessPeriod, // Ten seconds
timeForEmissions: 100,
numAgentInstances: 1,
agentIds: [],
threshold: 1,
configHash: HashZero,
proxyHash: HashZero,
serviceRegistry: AddressZero,
activityChecker: AddressZero
};
const maxInactivity = serviceParams.maxNumInactivityPeriods * livenessPeriod + 1;

beforeEach(async function () {
signers = await ethers.getSigners();
deployer = signers[0];

const ServiceRegistry = await ethers.getContractFactory("ServiceRegistryL2");
serviceRegistry = await ServiceRegistry.deploy("Service Registry L2", "SERVICE", "https://localhost/service/");
await serviceRegistry.deployed();
serviceParams.serviceRegistry = serviceRegistry.address;

const ServiceRegistryTokenUtility = await ethers.getContractFactory("ServiceRegistryTokenUtility");
serviceRegistryTokenUtility = await ServiceRegistryTokenUtility.deploy(serviceRegistry.address);
await serviceRegistry.deployed();

const OperatorWhitelist = await ethers.getContractFactory("OperatorWhitelist");
operatorWhitelist = await OperatorWhitelist.deploy(serviceRegistry.address);
await operatorWhitelist.deployed();

const ServiceManagerToken = await ethers.getContractFactory("ServiceManagerToken");
serviceManager = await ServiceManagerToken.deploy(serviceRegistry.address, serviceRegistryTokenUtility.address,
operatorWhitelist.address);
await serviceManager.deployed();

const Token = await ethers.getContractFactory("ERC20Token");
token = await Token.deploy();
await token.deployed();

const GnosisSafe = await ethers.getContractFactory("GnosisSafe");
gnosisSafe = await GnosisSafe.deploy();
await gnosisSafe.deployed();

const GnosisSafeProxyFactory = await ethers.getContractFactory("GnosisSafeProxyFactory");
gnosisSafeProxyFactory = await GnosisSafeProxyFactory.deploy();
await gnosisSafeProxyFactory.deployed();

const FallbackHandler = await ethers.getContractFactory("DefaultCallbackHandler");
fallbackHandler = await FallbackHandler.deploy();
await fallbackHandler.deployed();

const GnosisSafeMultisig = await ethers.getContractFactory("GnosisSafeMultisig");
gnosisSafeMultisig = await GnosisSafeMultisig.deploy(gnosisSafe.address, gnosisSafeProxyFactory.address);
await gnosisSafeMultisig.deployed();

const GnosisSafeProxy = await ethers.getContractFactory("GnosisSafeProxy");
const gnosisSafeProxy = await GnosisSafeProxy.deploy(gnosisSafe.address);
await gnosisSafeProxy.deployed();
const bytecode = await ethers.provider.getCode(gnosisSafeProxy.address);
bytecodeHash = ethers.utils.keccak256(bytecode);
serviceParams.proxyHash = bytecodeHash;

const StakingFactory = await ethers.getContractFactory("StakingFactory");
stakingFactory = await StakingFactory.deploy(AddressZero);
await stakingFactory.deployed();

const Contributors = await ethers.getContractFactory("Contributors");
contributors = await Contributors.deploy();
await contributors.deployed();

const ContributorsProxy = await ethers.getContractFactory("ContributorsProxy");
const proxyData = contributors.interface.encodeFunctionData("initialize", []);
contributorsProxy = await ContributorsProxy.deploy(contributors.address, proxyData);
await contributorsProxy.deployed();
contributors = await ethers.getContractAt("Contributors", contributorsProxy.address);

const ContributeManager = await ethers.getContractFactory("ContributeManager");
contributeManager = await ContributeManager.deploy(contributorsProxy.address, serviceManager.address,
token.address, stakingFactory.address, gnosisSafeMultisig.address, fallbackHandler.address,
agentId, defaultHash);

const ContributeActivityChecker = await ethers.getContractFactory("ContributeActivityChecker");
contributeActivityChecker = await ContributeActivityChecker.deploy(contributorsProxy.address, livenessRatio);
await contributeActivityChecker.deployed();
serviceParams.activityChecker = contributeActivityChecker.address;

const StakingToken = await ethers.getContractFactory("StakingToken");
stakingTokenImplementation = await StakingToken.deploy();
const initPayload = stakingTokenImplementation.interface.encodeFunctionData("initialize",
[serviceParams, serviceRegistryTokenUtility.address, token.address]);
const tx = await stakingFactory.createStakingInstance(stakingTokenImplementation.address, initPayload);
const res = await tx.wait();
// Get staking contract instance address from the event
const stakingTokenAddress = "0x" + res.logs[0].topics[2].slice(26);
stakingToken = await ethers.getContractAt("StakingToken", stakingTokenAddress);

// Set service manager
await serviceRegistry.changeManager(serviceManager.address);
await serviceRegistryTokenUtility.changeManager(serviceManager.address);

// Mint tokens to the service owner and the operator
await token.mint(deployer.address, initSupply);

// Whitelist gnosis multisig implementations
await serviceRegistry.changeMultisigPermission(gnosisSafeMultisig.address, true);

// Set the manager of contributorsProxy
contributors.changeManager(contributeManager.address);

// Fund the staking contract
await token.approve(stakingTokenAddress, ethers.utils.parseEther("1"));
await stakingToken.deposit(ethers.utils.parseEther("1"));
});

context("Initialization", function () {
});

context("Contribute manager", function () {
it.only("Mint and stake", async function () {
await token.approve(contributeManager.address, serviceParams.minStakingDeposit * 2);

await contributeManager.createAndStake(socialId, stakingToken.address, {value: 2});
});
});
});
Loading

0 comments on commit bc9a4e9

Please sign in to comment.