Oyster Credit: Enabling Seamless Access to Marlin’s TEE Marketplace
Wouldn’t it be great if devs could explore and experience the Marlin TEE marketplace without upfront costs? To reduce the barrier to entry, we introduce Oyster Credit, a token that functions like free credits for builders.
Oyster Credit enables teams to test the Oyster platform, explore different workflows, and integrate Marlin into their processes without committing USDC upfront. This approach encourages more teams to engage with the Trusted Execution Environment (TEE) Marketplace, fostering greater adoption and platform growth.
Initially, USDC grants were considered for onboarding teams, but they had a key limitation—once distributed, USDC could be spent outside the ecosystem. Instead, Oyster Credit ensures grants are used solely within Marlin, aligning incentives with platform growth while maintaining control over fund distributions.
This offers teams a structured way to access and utilize confidential computation while ensuring that credits are spent meaningfully within the ecosystem.
Design of the Credit System
Initial Design and Challenges of Credit Manager
Initially, the Credit system was designed as a third-party contract called the Credit Manager, which operated alongside the Oyster Market contract. In this design, Credit tokens were allocated by increasing the internal balance of the Credit Manager, acting as a wrapper contract. Users had to interact with the Oyster Market through the Credit Manager to utilize their allocated credits.
However, this design introduced four major issues:
-
Job Ownership and UX Complexity
Since the Credit Manager acted as a wrapper contract, users had to interact with the Oyster Market through it instead of directly. This introduced multiple entry points for job management, making interactions more fragmented and adding unnecessary complexity to the user experience." -
Complexity in Managing Job Balances
When opening a job through the Credit Manager, multiple balance management scenarios had to be considered:- Jobs funded entirely with Credit
- Jobs funded with both Credit and USDC
- Jobs funded exclusively with USDC
This significantly increased the complexity of interactions with the Oyster Market. Additionally, even though opening a job with only USDC via the Credit Manager was not intended as a normal use case, it became necessary for users planning to deposit Credit later, creating an unintended design dilemma.
-
Settlement Issues and Redundant Balance Tracking
When a job was opened through the Credit Manager, the deposited Credit tokens were converted to USDC within the Oyster Market. To maintain accurate balance records, the Credit Manager had to mirror the balance information from the Oyster Market every time an interaction occurred. This led to unnecessary logic duplication and increased gas costs. -
Untracked Deposits and Priority Deduction Issues
Since the Oyster Market does not enforce access control on deposits (anyone can deposit into any job ID), users could manually deposit USDC into a job that was originally opened via the Credit Manager. In such cases, the Credit Manager would be unaware of this additional balance, creating discrepancies. To resolve this, the system would need to prioritize deducting USDC over Credit until the untracked balance was fully used. However, this contradicted the intended Credit-first spending logic, deviating from the original design goals.
To address these challenges, we redesigned the Credit system to enhance usability, remove unnecessary complexity, and integrate seamlessly with the Oyster Market.
Latest Design of Credit System
For the reasons above, we decided to upgrade the Oyster Market contract to handle Credit tokens internally as part of a new Credit design.
By integrating Credit management directly into the Oyster Market contract, this upgrade eliminates the need for a separate Credit Manager, reducing complexity, redundant logic, and UX friction. Additionally, by implementing Credit as an ERC20 token, users can directly view and track their Credit balance like any other ERC20 token.
The following are the key characteristics of the newly designed Credit System:
- Can be used as equivalent to 1 USDC within the Oyster Market.
- Backed by a USDC reserve, ensuring that Credit tokens remain usable within the ecosystem while maintaining controlled liquidity.
- Non-transferable between wallets—once received, Credit can only be used within the Oyster Market and cannot be transferred elsewhere.
- Configured with
decimals = 6
, matching USDC to ensure precision and compatibility.
By implementing Oyster Credit, we provide teams with a structured way to access and utilize the Oyster Market while ensuring that credits are spent meaningfully within the ecosystem. Below, we take a closer look at how the Credit system operates within the Oyster Market at a higher level.
How Oyster Credit Integrates with the Oyster Market
With the new integrated design, Oyster Credit is seamlessly embedded within the Oyster TEE Market. Now, let’s explore how Credit interacts with the market, including deposits, withdrawals, and controlled transfers.
Controlled Transfers via TRANSFER_ALLOWED_ROLE
To ensure Credit tokens are used exclusively within the Oyster Market, transfers are strictly controlled. The system enforces role-based transfer permissions, allowing only authorized entities to move Credit tokens.
To transfer Credit tokens, either the sender or recipient must hold the TRANSFER_ALLOWED_ROLE
. This role is granted only to administrator accounts and the Oyster Market V1 contract, ensuring that Credit tokens can only be used within the Oyster Market.
Deposit
When a user opens a job using the jobOpen
function or deposits into an existing job using the jobDeposit
function, they must specify the amount
they wish to deposit.
At this point, the user can adjust the allowance of their Credit tokens to control how much of the deposit will be made using Credit. The deposit logic works as follows:
First, the system calculates the spendable Credit balance as the minimum of the user’s Credit allowance
and balance
. It then compares this value against the desired deposit amount
.
- If the spendable Credit balance exceeds the deposit amount, the entire amount is deposited using Credit tokens.
- If the spendable Credit balance is less than the deposit amount, the remaining portion is automatically covered using USDC.
For example, if the specified deposit amount
is 100 and the spendable Credit balance is 10, the user will deposit 10 in Credit and the remaining 90 in USDC. On the other hand, if the spendable Credit balance is 200, the full 100 will be deposited using Credit, leaving the user with 100 Credit tokens remaining (for simplicity, decimals are omitted).
Withdraw
In contrast to deposits, withdrawals prioritize USDC. When a user initiates a withdrawal from a specific job by calling the jobWithdraw
function, they provide the desired amount
to withdraw.
- If the job’s USDC balance is sufficient, the full amount is withdrawn in USDC. Otherwise, the shortfall is automatically covered using Credit tokens.
- If the USDC balance is less than the withdrawal amount, the remaining portion is withdrawn from the job’s Credit balance.
Naturally, if the Credit balance is insufficient to cover the remainder, the transaction will revert.
Settle and Redeem
Beyond deposits and withdrawals, Oyster Credit also plays a key role in job settlement. When a job is completed, Credit tokens are prioritized for payments, with a built-in redemption mechanism ensuring seamless value conversion."
The redeemAndBurn
function burns a specified amount of Credit tokens and redeems an equivalent amount of USDC. To call this function, the caller must have the REDEEMER_ROLE
, which is exclusively granted to the Oyster Market contract.
Job payments in the Oyster Market are settled using Credit first. Once depleted, the system deducts the remaining amount from the job’s USDC balance.
Get in touch on our socials (X or Telegram) if you’d like some credits to deploy on Marlin’s TEE compute marketplace!