Smart Contract

Smart contracts are what make the impactMarket protocol work. And this page is dedicated to that, where we started (alpha), until where we are and the functionalities of the latest version, in this case, v2.
To find the most recent version, its addresses, and audits, please visit


What's new

Two new entities: ambassadors and council.
Communities have a limit of beneficiaries.
Managers will only be able to add/remove/lock/unlock beneficiaries and request funds to the community.
Staking! Stake your PACTs, get more on donations by staking.

The most relevant changes


Each community has an ambassador. The ambassador is responsible for adding and removing managers. The ambassador can also lock and unlock a community. A locked community only allow managers to remove beneficiaries. A removed manager can be re-added. Can also define the limit of number of beneficiaries in a community.
The ambassador is assigned to a community at the moment that it claims the community using ambassadors' dashboard. The community can later be transferred to another ambassador if necessary or an ambassador can be fully replaced. Only the entity responsible for that ambassador, or the council can do that.

Community approvals

Communities are now Council's responsibility. The Council works pretty much the same way as the DAO does, with two differences. It doesn't own anything, unlike the DAO that owns the protocol. And the voting is 1:1, not requiring PACT delegation or anything. Also there are not limit of proposals one can open, nor a limit of time to wait until approving a proposal.
It has the power to control most UBI features. Accepts new communities, remove communities, change UBI parameters and tranches. It can also do most of ambassadors' activities.


Read more here.


What's new

impactMarket is now a DAO.
The DAO is controlled by a set of contracts, the Delegator, the Delegate, and the Timelock. It also has a Treasury.
Communities now are much more controllable through the Community Admin contract which is owned by the DAO. Any change requires a new proposal.
On v1 we've also deployed a Donation Miner contract, which is what calculates rewards for donors.
All these contracts are migratable, controlled through proxies, all owned by the DAO.
The contracts are fully documented. Please visit the repository here.

The most relevant changes


The DAO is a set of three contracts. The Delegator, the Delegate, and the Timelock. It is responsible for everything happening on the protocol. Every change will go through a proposal that will receive votes from PACT token holders.


Treasury is where all the assets are. The treasury holds the donations from which communities will be able to request funds. as well as any other asset.

Community Admin

The Community Admin is the contract responsible for all communities. It's a factory and an admin at the same time. It has the capability of deploying new communities, migrating, removing, changing community implementations, changing community parameters such as the UBI parameters and the tranches (min and max). And it can also add and remove managers.
The Community Admin actions can only be executed by the owner and it's owned by the DAO. Meaning that each action mentioned above needs to be included in a proposal.


The most relevant change to the community contract is the possibility to request funds from the DAO treasury. Communities have a min and max tranche, which defines the limit to what they can get from the treasury. When a proposal to create a community is executed, the community receives the min tranch amount from the DAO. The first manager also receives $0.05 to pay for fees.
Besides that, a community is now upgradable, meaning that, it's possible to change the implementation of a community through a proposal without the need to migrate its beneficiaries.
Previously the intervals (such as base interval and increment interval) were calculated in second, using block timestamp, as an opposite to now, where intervals are counted in blocks. Together with this change comes a fix on changing parameters (previously it was not possible to change the base interval).
There's also a new parameter called "decrease step", which, if set to a value higher than zero, decreases that amount from the max claim amount. For example, if it's $0.01, then every time a beneficiary is added, $0.01 will be decreased on the max claim for every beneficiary in that community.


During the alpha version, smart contracts were divided into three. ImpactMarket, CommunityFactory, and Community.


Its only role is to accept new communities. This will be replaced by a mechanism (already under development) with voting for new communities.


Its only role is to deploy new Community contracts. One contract per community. This contract is controlled by ImpactMarket.


This is the contract used by communities. There's one contract per community. This allows individual donations to communities.
Below are listed the public methods that can be called to get information from the contract.
// When the beneficiary can claim again (timestamp)
mapping(address => uint256) public cooldown;
// What was the last interval when the user claim.
// This is used to calculate the next interval
mapping(address => uint256) public lastInterval;
// How much has the beneficiary claimed so far.
mapping(address => uint256) public claimed;
// In what state is the beneficiary (enum BeneficiaryState {NONE, Valid, Locked, Removed})
mapping(address => BeneficiaryState) public beneficiaries;
// community amount per claim (in cUSD)
uint256 public claimAmount;
// community base interval (we have been using 1 day or 1 week) (in seconds)
uint256 public baseInterval;
// community increment interval (in seconds)
uint256 public incrementInterval;
// community maximun claim per beneficiary (in cUSD)
uint256 public maxClaim;
// if the community was migrated, will have here the address
address public previousCommunityContract;
// impactMarket contract address
address public impactMarketAddress;
// cUSD contract address
address public cUSDAddress;


Important note: for external integrations, when a manager tries to add an address as a manager or a beneficiary, that address needs to first be registered in the system, otherwise, it will show an error has mentioned in add beneficiary section. To avoid this, please make use of the /api/user/auth endpoint. For more information look at the API section.
* @dev Allow community managers to add other managers.
function addManager(address _account) external onlyManagers;
* @dev Allow community managers to remove other managers.
function removeManager(address _account) external onlyManagers;
* @dev Allow community managers to add beneficiaries.
function addBeneficiary(address _account) external onlyManagers;
* @dev Allow community managers to lock beneficiaries.
function lockBeneficiary(address _account) external onlyManagers;
* @dev Allow community managers to unlock locked beneficiaries.
function unlockBeneficiary(address _account) external onlyManagers;
* @dev Allow community managers to remove beneficiaries.
function removeBeneficiary(address _account) external onlyManagers;
* @dev Allow beneficiaries to claim.
function claim() external onlyValidBeneficiary;
* @dev Allow community managers to edit community variables.
function edit(
uint256 _claimAmount,
uint256 _maxClaim,
uint256 _baseInterval,
uint256 _incrementInterval
) external onlyManagers;