Skip to content

About

Morcast Payment Protocol: escrow, settlement and claims for creator campaigns on Base.

Topics

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

Morcast Payment Protocol

On-chain escrow and settlement for Morcast creator campaigns on Base.

A brand escrows a campaign budget in USDC or MOR. After the campaign ends, Morcast publishes the measured results and settles the campaign once. The contract then pays the protocol fee, lets creators claim their share against a Merkle root, and returns the unspent budget to the brand. If the campaign is not settled within its settlement window, the brand can withdraw the full budget.

Status

Protocol v1 is released as version 1.0.0 and deployed on Base (Deployments). Morcast's staging runs on Base Sepolia. Not audited.

Component State
Escrow contract (MorcastEscrow) Implemented. Unit, invariant and Base fork tests
Settlement arithmetic (SettlementMath) Implemented, unit- and fuzz-tested
Deployment scripts Implemented. Used for the Base deployment and the Base Sepolia staging deployment (Deployments)
TypeScript SDK: settlement, payouts, metrics Implemented, tested against the shared vectors
TypeScript SDK: document hashing, payout Merkle trees Implemented. Trees verified against the contract
TypeScript SDK: result dataset and verifier (morcast-verify) Implemented. Verified end to end on a local node
Security Internal review completed, no critical, high or medium findings. External audit pending

Usage

A brand approves the escrow for the budget and creates the campaign:

IERC20(usdc).approve(address(escrow), budget);
uint256 id = escrow.createCampaign(usdc, budget, target, startAt, endAt, manifestHash);

Between Day 5 and Day 10 after endAt, the settler settles the campaign with the recognized total from the published result dataset:

escrow.settle(id, recognized, merkleRoot, resultHash);

Then each party collects its share:

escrow.claim(id, wallet, amount, proof); // creator payout; anyone may submit it
escrow.withdrawFee(id);                  // protocol fee to the treasury; anyone may call it
escrow.withdrawBrand(id);                // unspent budget back to the brand

If the campaign is not settled before Day 10, the brand calls withdrawBrand(id) from Day 10 to recover the whole budget.

The owner, a wallet Morcast holds, operates the escrow. It can replace the settler and the treasury, choose tokens and pause creation for new campaigns, void a funded campaign (the budget goes back to its brand) and recover tokens sent to the escrow by mistake. It can never move a campaign's funds anywhere else.

Anyone can check a published result dataset, and compare it with the escrow, with the SDK package from a release:

npx --package=https://github.com/Morphora-Lab/morcast-protocol/releases/download/v1.0.0/morcast-protocol-1.0.0.tgz \
  morcast-verify result.json --rpc-url https://mainnet.base.org

Example

A brand escrows 100,000 USDC for a target of 1,000,000 qualified views, and Morcast recognizes 640,000:

Party Receives
Morcast treasury (fee, 20% of spent) 12,800 USDC
Creators (pool, 80% of spent) 51,200 USDC
Brand (refund) 36,000 USDC

The brand pays for 64% of the target, so 64,000 USDC is spent.

Documentation

  • Escrow contract: roles, timeline, functions, payout leaves and security properties.
  • Settlement arithmetic: creator scores, the budget split and creator payouts.
  • Metrics: exact decimals and the Integration retention metric.
  • Hashing and Merkle trees: canonical JSON for manifestHash and resultHash, and payout tree construction.
  • Result dataset: the published result format, reason codes and what the verifier checks.
  • Security: trust model, internal review findings and verified properties.
  • Deployment: deploying to Base mainnet, other networks and a local Anvil node.
  • Versions and upgrades: how a new version is released and what off-chain systems must support.
  • TypeScript SDK: the protocol arithmetic for off-chain services and verifiers.

Development

Requirements: Foundry 1.8 or later.

git clone --recurse-submodules https://github.com/Morphora-Lab/morcast-protocol.git
cd morcast-protocol
forge build
forge test

Dependencies are Git submodules pinned in foundry.lock: forge-std v1.17.0 and OpenZeppelin Contracts v5.7.0.

The TypeScript SDK lives in sdk/ and has its own instructions.

Tests

Suite Location Checks
Unit test/*.t.sol Every function, revert path and time boundary.
Fuzz testFuzz_* functions Settlement and payout properties for random inputs.
Invariant test/invariant/ Across random multi-campaign sequences, escrow balances equal outstanding obligations and settled campaigns follow the formula.
Fork test/fork/ Full lifecycle with the real USDC and MOR contracts on Base mainnet. Skipped unless BASE_RPC_URL is set.
Vectors vectors/ Numeric examples from the specification, shared with off-chain implementations.
End-to-end scripts/e2e-local.sh On a local Anvil node: deploy, create the example campaign, settle it from examples/result-dataset.json, verify it on-chain and claim every payout with SDK proofs.
forge test                                              # unit, fuzz and invariant tests
BASE_RPC_URL=https://mainnet.base.org forge test --match-path "test/fork/*"
(cd sdk && pnpm install && pnpm build) && scripts/e2e-local.sh

Releases

Versions follow semantic versioning. A tag such as v1.0.0-rc.1 marks a pre-release. Pushing a version tag on main runs the release workflow. It tests and packs the SDK, attests the package's build provenance and publishes a GitHub release with the package attached. The workflows pin every action to a commit hash, and Dependabot proposes updates to them and to the SDK's packages weekly.

Release State
v1.0.0-rc.1 Release candidate of protocol v1: feature-complete, internally reviewed. External audit pending, not deployed
v1.0.0-rc.2 Adds the escrow's code hash to the SDK (ESCROW_CODE_HASH, isGenuineEscrow)
v1.0.0-rc.3 A creator may take part in a campaign with several accounts. Each creator in a result dataset lists its accounts, and each account belongs to one wallet
v1.0.0-rc.4 The contract takes the product's name, MorcastEscrow. Its rules and its ABI are the same. Its code hash is new, so a deployment of an earlier release is not this release's escrow
v1.0.0 The first release of protocol v1, deployed on Base. The contract is the one of v1.0.0-rc.4, so its code hash is the same. No external audit yet

The escrow's VERSION() names the contract version a deployment runs. See Versions and upgrades.

License

MIT

About

Morcast Payment Protocol: escrow, settlement and claims for creator campaigns on Base.

Topics

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages