Deploying Alpen smart contracts
In this walkthrough we will go through creating a very simple Tornado Cash-like mixer contract, deploying it, and doing some transfers.
Deploying a mixer contract
Follow the official steps to install Foundry.
Initialize a project
forge init simple_mixer
cd simple_mixerThere should already be a
Counter.solfile insidesrc. Let's create a new onesrc/SimpleMixer.soland write the following to that file:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract SimpleMixer {
struct Deposit {
uint256 amount;
bytes32 commitment;
}
mapping(bytes32 => bool) public commitments; // Track unique deposits by commitment
mapping(bytes32 => bool) public nullifiers; // Prevent double withdrawals
mapping(bytes32 => uint256) public deposits; // Track deposit amounts per commitment
event DepositMade(bytes32 indexed commitment, uint256 amount);
event WithdrawalMade(address indexed recipient, uint256 amount);
// Make a deposit with a unique commitment hash
function deposit(bytes32 commitment) external payable {
require(msg.value > 0, "Deposit must be greater than 0");
require(!commitments[commitment], "Commitment already used");
commitments[commitment] = true;
deposits[commitment] = msg.value; // Track the deposited amount for the commitment
emit DepositMade(commitment, msg.value);
}
// Withdraw anonymously using a nullifier and commitment proof (simplified here)
function withdraw(
address payable recipient,
bytes32 commitment,
bytes32 nullifier
) external {
require(deposits[commitment] > 0, "Invalid or already withdrawn commitment");
require(!nullifiers[nullifier], "Nullifier already used");
// Here, you'd typically verify a zk-SNARK proof for true anonymity (skipped for this example)
uint256 amount = deposits[commitment];
// Mark the nullifier as used to prevent double spending
nullifiers[nullifier] = true;
deposits[commitment] = 0; // Prevent further withdrawals for this commitment
recipient.transfer(amount); // Transfer only the amount associated with this deposit
emit WithdrawalMade(recipient, amount);
}
}Compile the contract:
forge build
Before we deploy the contract, we need to make sure we are running an Alpen client or can connect to the Alpen network. Add the following lines to a
.envfile in your project folder:
And run source .env to load those in the shell session.
Deploy the contract:
When it completes successfully, you should see something like the following. Note the
Deployed toaddress which is the contract address.
Congratulations! We have now successfully deployed the mixer contract.
Depositing and withdrawing with cast
Create a commitment with some data:
cast keccak256 <some data string>Also create a nullifier:
cast keccak256 <some nullifier string>Deposit some amount to the mixer:
You should now see some amount deducted from your account.
Withdraw from the mixer.
The recipient address should now have received the withdrawn amount.
Last updated