Dottyland Impact Self = 100 USDC staked on Spirals

Kärri Brewster-Palts
Dottyland
Published in
3 min readMar 16, 2023

--

Impact is baked into the existence of the Impact Self. Per every Impact Self, Dottyland automatically stakes 100 USDC towards climate projects with Spirals Protocol.

Dottyland private beta claim flow view

Why?

As we’ve continued to work on the Impact Self beta, we’ve also been addressing the barriers users might come across when claiming their Impact Self, based on testers’ feedback.

Our early version is based on anyone being able to claim an Impact Self as long as their impact score is > 0. However, though our list of data sources is ever-expanding, it is still limited compared to the wide range of climate-positive actions individuals of different profiles and lifestyles take. Therefore, we looked for a way in which the sheer fact of claiming an Impact Self could also have direct climate-positive action baked in.

Now, one option would have been to just integrate offsetting, of course but 1) we wanted to go further than that and support climate projects that make positive impact possible in the first place and 2) the Impact Self as an impact identity does not have a price so the economics of direct offsetting would have had a significant impact on our limited budget.

If you’ve read this far then it’ll make complete sense to you that we chose Spirals Protocol as our pilot integration for baked-in impact.

Spirals

The logic is simple — per every Impact Self claimed, Dottyland stakes 100 USDC with Spirals Protocol (from Dottyland’s funds, with the principle being extractable). This action adds to the individual’s impact score and enables them to claim their Impact Self. Spirals, in turn, redirects the generated yield towards verified climate projects.

Dottyland beta dashboard view snapshot

HOW?
The implementation of our solution is straightforward and we encourage others to check it out and implement it on their own contracts. Our implementation uses an external contract called Depositr, which holds funds (both USDC from Dottyland and gUSDC wrapped by Spirals) and handles depositing and withdrawing from the Spirals Vault. We’ve promised to leave the USDC invested in Spirals for a certain time period, so we implemented a vesting mechanism that releases the gUSDC linearly over a 30-day period.
The most important function in Depositr is depositToSpirals, which deposits USDC into a Spirals Vault and vests it over time. The function also checks if there are enough funds and whether a user has already triggered a deposit.
Here’s the function code:

```Solidityfunction depositToSpirals(address _onBehalfOf) external overrideonlyImpactSelf updateVestingVariables {uint256 _amount = amountToDeposit;IERC20 _token = IERC20(token);`ISpiralsImpactVault _gToken = ISpiralsImpactVault(gToken);// PHASE 1: Check if the Depositor contract has enough funds.if (_token.balanceOf(address(this)) < _amount) {  return;}// PHASE 2: Check if the user has already triggered a deposit.if (depositingUsers[_onBehalfOf]) {  return;}depositingUsers[_onBehalfOf] = true;// PHASE 3: Approve the Spirals contract to transfer the depositor's tokens.bool successfulApproval = _token.approve(address(_gToken), _amount);require(successfulApproval);// PHASE 4: Deposit the amount in the Spirals Vault.uint256 initialAmount = _gToken.balanceOf(address(this));_gToken.deposit(_amount, address(this));locked += _gToken.balanceOf(address(this)) - initialAmount;// PHASE 5: Emit an event to log the deposit.emit DepositedToSpirals(_amount, _onBehalfOf);}```The code is available for inspection at the contract address 0x5d48f3847e810f5777fcea144e63406aa22eb297 
The Impact Self contract is even simpler. After an Impact Self is minted, we call the depositToSpirals function. Here's the code:
```Solidity
function mintForUser(address sender) private nonReentrant { require(balanceOf(sender) == 0, "Already claimed"); require(getScore(sender) > 0, "User has no score"); _tokenIds.increment(); _safeMint(sender, _tokenIds.current()); // Trigger a deposit on Spirals on behalf of the user. if (depositor != address(0)) IDepositor(depositor).depositToSpirals(sender);}The Impact Self contract code is available for inspection at the contract address 0x7731fc3842ce3d03504aec26f0dfe5f0ccc44e9a

Now, if you’ve read this far, then you might have suggestions for how to do it differently or you’re ready to become an Impact Self beta tester (in exchange for some pretty hot swag).

Either way, pls get in touch with us here.

Kärri

--

--

Kärri Brewster-Palts
Dottyland

Co-founder @ Dottyland. Turning climate-positive behaviour into functional on-chain identities.