Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MVP of assurance contract contracts + tests #44

Draft
wants to merge 6 commits into
base: dev
Choose a base branch
from

Conversation

owocki
Copy link

@owocki owocki commented Oct 18, 2024

An assurance contract is a type of agreement in which participants commit to funding a public good or project only if a threshold of contributions is met. If the total pledged contributions reach the predetermined amount, the project moves forward, and participants fulfill their financial commitments. If the threshold isn't met, no one is obligated to contribute, and the project does not proceed.

This mechanism reduces the free-rider problem in public goods funding by ensuring that participants only pay if the project can be fully funded and implemented. It provides a way to align the interests of contributors, ensuring that everyone’s contributions are contingent on the collective success of the funding effort.

This PR adds an assurance contract and passing tests to the allo 2.1 repo

Features

  • Creation of Pools
  • Refund Pools
  • Payout Pools
  • Integrate into allocate/distribute functions
  • Integrate register() functionality
  • Webapp where you can interact w this
[PASS] testClaimFundsBeforeDeadline() (gas: 173184)
[PASS] testClaimFundsERC20() (gas: 268169)
[PASS] testClaimFundsETH() (gas: 213334)
[PASS] testInitializeERC20() (gas: 142273)
[PASS] testInitializeETH() (gas: 119991)
[PASS] testPledgeAfterDeadline() (gas: 125953)
[PASS] testPledgeERC20() (gas: 255340)
[PASS] testPledgeETH() (gas: 173698)
[PASS] testRefundBeforeDeadline() (gas: 171858)
[PASS] testRefundERC20() (gas: 256284)
[PASS] testRefundETH() (gas: 190767)
Suite result: ok. 11 passed; 0 failed; 0 skipped; finished in 842.63µs (850.83µs CPU time)

Run it yourself with

bun run test AssuranceContractStrategy

}

function _allocate(address[] memory, uint256[] memory, bytes memory, address) internal virtual override {
revert("AssuranceContract: Allocate not implemented");
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need to integrate the payout/refund txns here.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why? Isnt allocate in this case the pledge logic?

revert("AssuranceContract: Allocate not implemented");
}

function _distribute(address[] memory, bytes memory, address) internal virtual override {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would be nice if i just got a distribute function that could natively handle any type of distribution (merkle, drips, or otherwise)...

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. In this example however what would distribute do? like allocate - pledge, I think distribute should hold the logic of claimFunds

}

function _register(address[] memory, bytes memory, address) internal virtual override returns (address[] memory) {
revert("AssuranceContract: Register not implemented");
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think the current allo pool uses just naked addresses. need to use allo registry items per https://github.com/allo-protocol/allo-v2.1/blob/dev/contracts/core/Allo.md#register-recipient.

would be nice if this could be inherited from an upstream contract..

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could make use of the RecipientsExtension. Using the _register from the extensions includes this check

if (_recipientIdOrRegistryAnchor != address(0)) {
if (!_isProfileMember(_recipientIdOrRegistryAnchor, _sender)) {
revert UNAUTHORIZED();
}

Copy link

@0xOneTony 0xOneTony left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Took a peek, great effort! 🔥
I left a couple of comments when it comes to the logic for allocate and distribute. An improved design could be, having an extension AssuranceExtensions handling the logic for pledging and refunding along with some hooks, for added flexibility for custom code, and having a strategy CrowdFundAssuranceStrategy that uses this extension and integrates pledge into allocate (from extension) and claim funds for distribute to beneficiary.

}

/// @notice Mapping of pool IDs to Campaign structs
mapping(uint256 => Campaign) public campaigns;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see you have this mapping here, does this mean the strategy would be re-usable for multiple campaigns after each one finishes? If so it would be cleaner to also include a createCampaign function for pool managers that will basically create the campaign like you do in initialize

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i believe pool ID here is also reffering to the ID of the campaign, this might confuse people with Allo's pool IDs

}

function _allocate(address[] memory, uint256[] memory, bytes memory, address) internal virtual override {
revert("AssuranceContract: Allocate not implemented");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why? Isnt allocate in this case the pledge logic?

revert("AssuranceContract: Allocate not implemented");
}

function _distribute(address[] memory, bytes memory, address) internal virtual override {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. In this example however what would distribute do? like allocate - pledge, I think distribute should hold the logic of claimFunds

}

function _register(address[] memory, bytes memory, address) internal virtual override returns (address[] memory) {
revert("AssuranceContract: Register not implemented");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could make use of the RecipientsExtension. Using the _register from the extensions includes this check

if (_recipientIdOrRegistryAnchor != address(0)) {
if (!_isProfileMember(_recipientIdOrRegistryAnchor, _sender)) {
revert UNAUTHORIZED();
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants