Skip to content

Commit

Permalink
refactor: staking verifier
Browse files Browse the repository at this point in the history
  • Loading branch information
kupermind committed Oct 23, 2024
1 parent 0b24408 commit a43e44f
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 35 deletions.
2 changes: 1 addition & 1 deletion contracts/contribute/ContributeActivityChecker.sol
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ contract ContributeActivityChecker {
/// @return nonces Set of a single service multisig nonce.
function getMultisigNonces(address multisig) external view virtual returns (uint256[] memory nonces) {
nonces = new uint256[](1);
// The nonces are equal to the social off-chain activity corresponding multisig activity
// The nonce is equal to the social off-chain activity corresponding to a multisig activity
nonces[0] = IContributors(contributorsProxy).mapMutisigActivities(multisig);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ error ServiceNotDefined(uint256 socialId);
/// @param serviceOwner Actual service owner.
error ServiceOwnerOnly(uint256 serviceId, address sender, address serviceOwner);

/// @title ContributeServiceManager - Smart contract for managing services for contributors
/// @title ContributeManager - Smart contract for managing services for contributors
/// @author Aleksandr Kuperman - <[email protected]>
/// @author Andrey Lebedev - <[email protected]>
/// @author Tatiana Priemova - <[email protected]>
/// @author David Vilela - <[email protected]>
contract ContributeServiceManager {
contract ContributeManager {
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 All @@ -60,18 +60,26 @@ contract ContributeServiceManager {
event Claimed(uint256 indexed socialId, address indexed serviceOwner, uint256 serviceId,
address indexed multisig, address stakingInstance);

// Contribute agent Id
uint256 public constant AGENT_ID = 6;
// Contributor service config hash mock
bytes32 public constant CONFIG_HASH = 0x0000000000000000000000000000000000000000000000000000000000000006;
// Contributors proxy contract address
// Number of agent instances
uint256 public constant NUM_AGENT_INSTANCES = 1;
// Threshold
uint256 public constant THRESHOLD = 1;
// Contributor agent Id
uint256 public immutable agentId;
// Contributor service config hash
bytes32 public immutable configHash;
// Contributors proxy address
address public immutable contributorsProxy;
// Service manager contract address
// Service manager address
address public immutable serviceManager;
// OLAS token address
address public immutable olas;
// Service registry address
address public immutable serviceRegistry;
// Service registry token utility address
address public immutable serviceRegistryTokenUtility;
// Staking factory address
address public immutable stakingFactory;
// Safe multisig processing contract address
address public immutable safeMultisig;
// Safe fallback handler
Expand All @@ -80,20 +88,43 @@ contract ContributeServiceManager {
// Nonce
uint256 internal nonce;

/// @dev ContributeServiceManager constructor.
/// @dev ContributeManager constructor.
/// @param _contributorsProxy Contributors proxy address.
/// @param _serviceManager Service manager address.
/// @param _olas OLAS token address.
/// @param _stakingFactory Staking factory address.
/// @param _safeMultisig Safe multisig address.
/// @param _fallbackHandler Multisig fallback handler address.
constructor(address _contributorsProxy, address _serviceManager, address _safeMultisig, address _fallbackHandler) {
/// @param _agentId Contributor agent Id.
/// @param _configHash Contributor service config hash.
constructor(
address _contributorsProxy,
address _serviceManager,
address _olas,
address _stakingFactory,
address _safeMultisig,
address _fallbackHandler,
uint256 _agentId,
bytes32 _configHash
) {
// Check for zero addresses
if (_contributorsProxy == address(0) || _serviceManager == address(0) || _safeMultisig == address(0) ||
_fallbackHandler == address(0)) {
if (_contributorsProxy == address(0) || _serviceManager == address(0) || _olas == address(0) ||
_stakingFactory == address(0) || _safeMultisig == address(0) || _fallbackHandler == address(0)) {
revert ZeroAddress();
}

// Check for zero values
if (_agentId == 0 || _configHash == 0) {
revert ZeroValue();
}

agentId = _agentId;
configHash = _configHash;

contributorsProxy = _contributorsProxy;
serviceManager = _serviceManager;
olas = _olas;
stakingFactory = _stakingFactory;
safeMultisig = _safeMultisig;
fallbackHandler = _fallbackHandler;
serviceRegistry = IService(serviceManager).serviceRegistry();
Expand All @@ -103,42 +134,39 @@ contract ContributeServiceManager {
/// @dev Creates and deploys a service for the contributor.
/// @param token Staking token address.
/// @param minStakingDeposit Min staking deposit value.
/// @param numAgentInstances Number of agent instances in the service.
/// @param threshold Threshold.
/// @return serviceId Minted service Id.
/// @return multisig Service multisig.
function _createAndDeploy(
address token,
uint256 minStakingDeposit,
uint256 numAgentInstances,
uint256 threshold
uint256 minStakingDeposit
) internal returns (uint256 serviceId, address multisig) {
// Set agent params
IService.AgentParams[] memory agentParams = new IService.AgentParams[](1);
agentParams[0] = IService.AgentParams(uint32(numAgentInstances), uint96(minStakingDeposit));
IService.AgentParams[] memory agentParams = new IService.AgentParams[](NUM_AGENT_INSTANCES);
agentParams[0] = IService.AgentParams(uint32(NUM_AGENT_INSTANCES), uint96(minStakingDeposit));

// Set agent Ids
uint32[] memory agentIds = new uint32[](1);
agentIds[0] = uint32(AGENT_ID);
uint32[] memory agentIds = new uint32[](NUM_AGENT_INSTANCES);
agentIds[0] = uint32(agentId);

// Set agent instances as [msg.sender]
address[] memory instances = new address[](1);
address[] memory instances = new address[](NUM_AGENT_INSTANCES);
instances[0] = msg.sender;

// Create a service owned by this contract
serviceId = IService(serviceManager).create(address(this), token, CONFIG_HASH, agentIds,
agentParams, uint32(threshold));
serviceId = IService(serviceManager).create(address(this), token, configHash, agentIds,
agentParams, uint32(THRESHOLD));

// Activate registration (1 wei as a deposit wrapper)
IService(serviceManager).activateRegistration{value: 1}(serviceId);

// Register msg.sender as an agent instance (numAgentInstances wei as a bond wrapper)
IService(serviceManager).registerAgents{value: numAgentInstances}(serviceId, instances, agentIds);
IService(serviceManager).registerAgents{value: NUM_AGENT_INSTANCES}(serviceId, instances, agentIds);

// Prepare Safe multisig data
uint256 localNonce = nonce;
uint256 randomNonce = uint256(keccak256(abi.encodePacked(block.timestamp, msg.sender, localNonce)));
bytes memory data = abi.encodePacked(address(0), fallbackHandler, address(0), address(0), uint256(0),
localNonce, "0x");
randomNonce, "0x");
// Deploy the service
multisig = IService(serviceManager).deploy(serviceId, safeMultisig, data);

Expand Down Expand Up @@ -167,36 +195,50 @@ contract ContributeServiceManager {
/// @param socialId Contributor social Id.
/// @param stakingInstance Contribute staking instance address.
function createAndStake(uint256 socialId, address stakingInstance) external payable {
// Check for zero value
if (socialId == 0) {
revert ZeroValue();
}

// Check for existing service corresponding to the social Id
(uint256 serviceId, address multisig, , ) = IContributors(contributorsProxy).mapSocialIdServiceInfo(socialId);
if (serviceId > 0) {
revert ServiceAlreadyStaked(socialId, serviceId, multisig);
}

// Check for staking instance validity
if(!IStaking(stakingFactory).verifyInstance(stakingInstance)) {
revert WrongStakingInstance(stakingInstance);
}

// Get the token info from the staking contract
// If this call fails, it means the staking contract does not have a token and is not compatible
address token = IStaking(stakingInstance).stakingToken();
// Check the token address
if (token != olas) {
revert WrongStakingInstance(stakingInstance);
}

// Get other service info for staking
uint256 minStakingDeposit = IStaking(stakingInstance).minStakingDeposit();
uint256 numAgentInstances = IStaking(stakingInstance).numAgentInstances();
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 != 1 || threshold != 1) {
if (numAgentInstances != NUM_AGENT_INSTANCES || threshold != THRESHOLD) {
revert WrongStakingInstance(stakingInstance);
}

// Calculate the total bond required for the service deployment:
uint256 totalBond = (1 + numAgentInstances) * minStakingDeposit;
uint256 totalBond = (1 + NUM_AGENT_INSTANCES) * minStakingDeposit;

// Transfer the total bond amount from the contributor
IToken(token).transferFrom(msg.sender, address(this), totalBond);
IToken(olas).transferFrom(msg.sender, address(this), totalBond);
// Approve token for the serviceRegistryTokenUtility contract
IToken(token).approve(serviceRegistryTokenUtility, totalBond);
IToken(olas).approve(serviceRegistryTokenUtility, totalBond);

// Create and deploy service
(serviceId, multisig) = _createAndDeploy(token, minStakingDeposit, numAgentInstances, threshold);
(serviceId, multisig) = _createAndDeploy(olas, minStakingDeposit);

// Stake the service
_stake(socialId, serviceId, multisig, stakingInstance);
Expand Down
8 changes: 5 additions & 3 deletions contracts/contribute/Contributors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ contract Contributors {
event ManagerUpdated(address indexed manager);
event SetServiceInfoForId(uint256 indexed socialId, uint256 indexed serviceId, address multisig,
address stakingInstance, address indexed serviceOwner);
event SetContributeAgentStatuses(address[] mechMarketplaces, bool[] statuses);
event SetContributeAgentStatuses(address[] contributeAgents, bool[] statuses);
event MultisigActivityChanged(address indexed senderAgent, address[] multisigs, uint256[] activityChanges);

// Version number
Expand Down Expand Up @@ -170,7 +170,7 @@ contract Contributors {
/// @dev Sets contribute agent statues.
/// @param contributeAgents Contribute agent addresses.
/// @param statuses Corresponding whitelisting statues.
function setMechMarketplaceStatuses(address[] memory contributeAgents, bool[] memory statuses) external {
function setContributeAgentStatuses(address[] memory contributeAgents, bool[] memory statuses) external {
// Check for the ownership
if (msg.sender != owner) {
revert OwnerOnly(msg.sender, owner);
Expand All @@ -181,7 +181,7 @@ contract Contributors {
revert WrongArrayLength(contributeAgents.length, statuses.length);
}

// Traverse all the mech marketplaces and statuses
// Traverse all contribute agents and statuses
for (uint256 i = 0; i < contributeAgents.length; ++i) {
if (contributeAgents[i] == address(0)) {
revert ZeroAddress();
Expand Down Expand Up @@ -214,4 +214,6 @@ contract Contributors {

emit MultisigActivityChanged(msg.sender, multisigs, activityChanges);
}


}
5 changes: 5 additions & 0 deletions contracts/contribute/interfaces/IStaking.sol
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,9 @@ interface IStaking {
/// @param serviceId Service Id.
/// @return Staking reward.
function claim(uint256 serviceId) external returns (uint256);

/// @dev Verifies a service staking contract instance.
/// @param instance Service staking proxy instance.
/// @return True, if verification is successful.
function verifyInstance(address instance) external view returns (bool);
}

0 comments on commit a43e44f

Please sign in to comment.