Energy-Fi Protocol: 去中心化能源金融协议技术解析

  • 木西
  • 发布于 3小时前
  • 阅读 24

概述Energy-FiProtocol是一个基于区块链的绿色能源交易与金融生态系统,通过智能合约实现能源资产的代币化、市场化交易、动态定价以及收益分配。本文将深入解析其核心合约架构、DAO治理机制以及质押分红系统。一、系统架构概览

概述

Energy-Fi Protocol 是一个基于区块链的绿色能源交易与金融生态系统,通过智能合约实现能源资产的代币化、市场化交易、动态定价以及收益分配。本文将深入解析其核心合约架构、DAO治理机制以及质押分红系统。

一、系统架构概览

层级 核心内容
资产层 BoykaYuriToken (ERC20) + GreenCarbonNFT (ERC721)
定价层 AlgorithmicEnergyPricing (动态定价算法)
市场层 GreenEnergyMarket (P2P 能源交易)
金融层 EnergyStaking (质押挖矿与分红)
治理层 AccessControl (DAO 治理与权限管理)

二、核心合约详解

2.1 BoykaYuriToken - 能源代币

// SPDX-License-Identifier: MIT
// Compatible with OpenZeppelin Contracts ^5.5.0
pragma solidity ^0.8.24;

import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {ERC20Burnable} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";

contract BoykaYuriToken is ERC20, ERC20Burnable, Ownable, ERC20Permit {
    constructor(address recipient, address initialOwner)
        ERC20("MyToken", "MTK")
        Ownable(initialOwner)
        ERC20Permit("MyToken")
    {
        _mint(recipient, 1000000 * 10 ** decimals());
    }
    function mint(address to, uint256 amount) public onlyOwner {
        _mint(to, amount);
    }
}

技术亮点:

  • 初始铸造 100万枚代币,由 recipient 接收
  • 支持 EIP-2612 许可标准,实现 gasless 转账
  • 仅所有者拥有铸币权限,控制通胀风险

    2.2 GreenCarbonNFT - 碳信用NFT

    
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.24;

import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";

contract GreenCarbonNFT is ERC721, Ownable { error AlreadyOffset(uint256 tokenId);

struct CarbonData { uint256 amountKG; bool isOffset; }
mapping(uint256 => CarbonData) public carbonRegistry;
uint256 private _nextTokenId;

constructor(address initialOwner) ERC721("GreenCarbon", "GCC") Ownable(initialOwner) {}

function mintCarbonCredit(address to, uint256, uint256 kgAmount) external onlyOwner {
    uint256 tokenId = _nextTokenId++;
    _safeMint(to, tokenId);
    carbonRegistry[tokenId] = CarbonData(kgAmount, false);
}

}

**应用场景:**

-   可再生能源项目方铸造碳信用NFT
-   企业购买NFT用于碳中和目标
-   链上透明记录,防止双重计算
### 2.3 AlgorithmicEnergyPricing - 算法定价引擎

采用 **AccessControl** 实现多角色治理的动态定价系统:

#### 核心公式

$$Price=BasePrice×(1+TargetMultiplier×(Load−Target)​÷100)$$

// SPDX-License-Identifier: MIT pragma solidity ^0.8.24;

import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol";

contract AlgorithmicEnergyPricing is AccessControl { bytes32 public constant GOVERNANCE_ROLE = keccak256("GOVERNANCE_ROLE"); bytes32 public constant ORACLE_ROLE = keccak256("ORACLE_ROLE");

uint256 public basePrice = 100;      // 基础价
uint256 public loadMultiplier = 50;  // 波动系数 (DAO治理)
uint256 public targetLoad = 1000;    // 额定负荷 (MW)
uint256 public lastReportedLoad;

constructor(address admin, address dao) {
    _grantRole(DEFAULT_ADMIN_ROLE, admin);
    _grantRole(GOVERNANCE_ROLE, dao);
    _grantRole(ORACLE_ROLE, admin); // 初始由管理员充当预言机
}

function updateLoadFromOracle(uint256 _load) external onlyRole(ORACLE_ROLE) {
    lastReportedLoad = _load;
}

function setPricingParameters(uint256 _multiplier, uint256 _base) external onlyRole(GOVERNANCE_ROLE) {
    loadMultiplier = _multiplier;
    basePrice = _base;
}

function getCurrentPrice() public view returns (uint256) {
    if (lastReportedLoad <= targetLoad) return basePrice;
    uint256 excessLoad = lastReportedLoad - targetLoad;
    uint256 dynamicPart = (loadMultiplier * excessLoad) / targetLoad;
    return basePrice + (basePrice * dynamicPart / 100);
}

}

#### 角色权限设计
| 角色                   | 权限     | 典型持有者   |
| :------------------- | :----- | :------ |
| `DEFAULT_ADMIN_ROLE` | 管理其他角色 | 协议部署者   |
| `GOVERNANCE_ROLE`    | 修改定价参数 | DAO治理合约 |
| `ORACLE_ROLE`        | 更新负荷数据 | 预言机节点   |

**治理优势:**

-   将定价权从单一所有者转移至DAO,实现去中心化治理
-   预言机角色独立,确保数据输入的可信度
-   参数调整需通过治理投票,防止恶意操纵
### 2.4 GreenEnergyMarket - 能源交易市场
```js
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {Pausable} from "@openzeppelin/contracts/utils/Pausable.sol";
import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol";

contract GreenEnergyMarket is Pausable, AccessControl {
    bytes32 public constant GOVERNANCE_ROLE = keccak256("GOVERNANCE_ROLE");
    bytes32 public constant DEPIN_DEVICE_ROLE = keccak256("DEPIN_DEVICE_ROLE");

    error UnauthorizedDevice(address device);
    error PriceAnomalyDetected(uint256 price);

    IERC20 public energyToken;
    address public treasury;

    struct Offer { address provider; uint256 amount; uint256 price; bool active; }
    mapping(uint256 => Offer) public offers;
    uint256 public nextOfferId;

    constructor(address _token, address _admin, address _dao) {
        energyToken = IERC20(_token);
        _grantRole(DEFAULT_ADMIN_ROLE, _admin);
        _grantRole(GOVERNANCE_ROLE, _dao);
    }

    function authorizeDevice(address _device) external onlyRole(DEFAULT_ADMIN_ROLE) {
        _grantRole(DEPIN_DEVICE_ROLE, _device);
    }

    function recordProduction(address _provider, uint256 _amount) external onlyRole(DEPIN_DEVICE_ROLE) {
        // 数据上链逻辑
    }

    function buyEnergy(uint256 _offerId) external whenNotPaused {
        Offer storage offer = offers[_offerId];
        uint256 totalCost = offer.amount * offer.price;
        uint256 fee = totalCost / 100; // 1% 手续费

        offer.active = false;
        energyToken.transferFrom(msg.sender, offer.provider, totalCost - fee);
        energyToken.transferFrom(msg.sender, treasury, fee);
    }

    function createOffer(uint256 _amount, uint256 _price, uint256) external whenNotPaused {
        offers[nextOfferId++] = Offer(msg.sender, _amount, _price, true);
    }

    function updatePriceSafe(uint256 _newPrice) external onlyRole(DEFAULT_ADMIN_ROLE) {
        if (_newPrice > 500) {
            _pause();
            revert PriceAnomalyDetected(_newPrice);
        }
    }

    function setTreasury(address _treasury) external onlyRole(GOVERNANCE_ROLE) {
        treasury = _treasury;
    }
}

安全防护机制

  • Pausable: 价格异常时自动暂停交易
  • AccessControl: 多层级权限管理
  • 价格异常检测: 当价格超过阈值时触发保护

    2.5 EnergyStaking - 质押分红池

    
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.24;

import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";

contract EnergyStaking is ReentrancyGuard { IERC20 public stakingToken; uint256 public totalStaked; mapping(address => uint256) public stakedBalance; mapping(address => uint256) public rewardMask; uint256 public accRewardPerShare;

constructor(address _token) { stakingToken = IERC20(_token); }

function stake(uint256 amount) external nonReentrant {
    _updateReward(msg.sender);
    stakingToken.transferFrom(msg.sender, address(this), amount);
    stakedBalance[msg.sender] += amount;
    totalStaked += amount;
}

// 接收国库转入的收益并更新全球每股收益
function notifyRewardAmount(uint256 reward) external {
    if (totalStaked > 0) {
        accRewardPerShare += (reward * 1e18) / totalStaked;
    }
}

function _updateReward(address user) internal {
    uint256 pending = (stakedBalance[user] * accRewardPerShare / 1e18) - rewardMask[user];
    if (pending > 0) { stakingToken.transfer(user, pending); }
    rewardMask[user] = stakedBalance[user] * accRewardPerShare / 1e18;
}

}

#### 分红闭环流程
```js
市场交易产生手续费
        ↓
手续费转入国库地址 (treasury)
        ↓
调用 notifyRewardAmount() 注入质押池
        ↓
更新 accRewardPerShare(全球每股收益)
        ↓
质押者调用 stake() / withdraw() 触发 _updateReward()
        ↓
自动计算并发放应得收益

三、测试用例解析

Energy-Fi Protocol Full DAO & Yield Integration ✔ 逻辑一致性:电价算法应与脚本预期严格匹配 (1475ms) ✔ DAO 治理:只有治理角色可以修改定价参数 (680ms) ✔ 分红闭环:市场交易产生手续费并自动分发给质押者 (716ms)

import assert from "node:assert/strict";
import { describe, it } from "node:test";
import { parseEther, keccak256 } from "viem";
import { network } from "hardhat";

describe("Energy-Fi Protocol Full DAO & Yield Integration", function () {
async function deployFixture() {
    const { viem } = await (network as any).connect();
    const [admin, user, iotDevice, dao] = await viem.getWalletClients();

    // 1. 部署全套合约
    const energyToken = await viem.deployContract("BoykaYuriToken", [admin.account.address, admin.account.address]);
    const carbonNFT = await viem.deployContract("GreenCarbonNFT", [admin.account.address]);
    const pricingLogic = await viem.deployContract("AlgorithmicEnergyPricing", [admin.account.address, dao.account.address]);
    const market = await viem.deployContract("GreenEnergyMarket", [energyToken.address, admin.account.address, dao.account.address]);
    const staking = await viem.deployContract("EnergyStaking", [energyToken.address]);

    // 2. 初始权限配置 (修复位置)
    // 计算 DEPIN_DEVICE_ROLE 的哈希值 (keccak256("DEPIN_DEVICE_ROLE"))
    const DEPIN_DEVICE_ROLE = keccak256(Buffer.from("DEPIN_DEVICE_ROLE"));

    // 使用 AccessControl 标准的 grantRole 函数授予权限
    await market.write.grantRole([DEPIN_DEVICE_ROLE, iotDevice.account.address], { account: admin.account });

    // 设置国库地址 (此函数在 Market 合约中由 GOVERNANCE_ROLE 调用)
    await market.write.setTreasury([staking.address], { account: dao.account });

    return { energyToken, carbonNFT, pricingLogic, market, staking, admin, user, iotDevice, dao };
  }
  it("逻辑一致性:电价算法应与脚本预期严格匹配", async function () {
    const { pricingLogic } = await deployFixture();
    const currentLoad = 1200n;
    const targetLoad = 1000n;
    const basePrice = 100n;
    const multiplier = 50n;

    await pricingLogic.write.updateLoadFromOracle([currentLoad]);

    const excessLoad = currentLoad - targetLoad; 
    const dynamicPart = (multiplier * excessLoad) / targetLoad; 
    const expectedPrice = basePrice + (basePrice * dynamicPart / 100n); 

    const currentPrice = await pricingLogic.read.getCurrentPrice();
    assert.equal(currentPrice, expectedPrice, "定价算法不一致");
  });

  it("DAO 治理:只有治理角色可以修改定价参数", async function () {
    const { pricingLogic, dao, user } = await deployFixture();

    // 治理角色修改参数成功
    await pricingLogic.write.setPricingParameters([80n, 110n], { account: dao.account });

    // 普通用户尝试修改应失败 (AccessControl 抛出错误)
    await assert.rejects(
      async () => {
        await pricingLogic.write.setPricingParameters([100n, 100n], { account: user.account });
      },
      /AccessControlUnauthorizedAccount/
    );
  });

  it("分红闭环:市场交易产生手续费并自动分发给质押者", async function () {
    const { energyToken, market, staking, admin, user } = await deployFixture();
    const stakeAmount = parseEther("1000");

    // 1. 用户质押代币
    await energyToken.write.transfer([user.account.address, stakeAmount], { account: admin.account });
    await energyToken.write.approve([staking.address, stakeAmount], { account: user.account });
    await staking.write.stake([stakeAmount], { account: user.account });

    // 2. 发生能源交易
    const amount = 100n;
    const price = parseEther("2");
    const totalCost = amount * price;
    await energyToken.write.approve([market.address, totalCost], { account: admin.account });
    await market.write.createOffer([amount, price, 3600n], { account: admin.account });
    await market.write.buyEnergy([0n], { account: admin.account });

    // 3. 注入分红 (手动模拟国库转账并通知,实际可由合约自动触发)
    const fee = totalCost / 100n;
    await energyToken.write.approve([staking.address, fee], { account: admin.account });
    await staking.write.notifyRewardAmount([fee], { account: admin.account });

    // 4. 用户领取收益
    const balanceBefore = await energyToken.read.balanceOf([user.account.address]);
    await staking.write.stake([0n], { account: user.account }); // 触发更新
    const balanceAfter = await energyToken.read.balanceOf([user.account.address]);

    assert.ok(balanceAfter > balanceBefore, "质押分红未到账");
  });
});

四、部署脚本

// scripts/deploy.js
import { network, artifacts } from "hardhat";
async function main() {
  // 连接网络
  const { viem } = await network.connect({ network: network.name });//指定网络进行链接

  // 获取客户端
  const [deployer,dao] = await viem.getWalletClients();
  const publicClient = await viem.getPublicClient();

  const deployerAddress = deployer.account.address;
   console.log("部署者的地址:", deployerAddress);
  // 加载合约
  const BoykaYuriTokenArtifact = await artifacts.readArtifact("BoykaYuriToken");
  const GreenCarbonNFTArtifact = await artifacts.readArtifact("GreenCarbonNFT");
  const AlgorithmicEnergyPricingArtifact = await artifacts.readArtifact("AlgorithmicEnergyPricing");
  const GreenEnergyMarketArtifact = await artifacts.readArtifact("GreenEnergyMarket");
 const EnergyStakingArtifact = await artifacts.readArtifact("EnergyStaking");
  // 部署(构造函数参数:recipient, initialOwner)
  const BoykaYuriTokenHash = await deployer.deployContract({
    abi: BoykaYuriTokenArtifact.abi,//获取abi
    bytecode: BoykaYuriTokenArtifact.bytecode,//硬编码
    args: [deployerAddress,deployerAddress],//部署者地址,初始所有者地址
  });
   const BoykaYuriTokenReceipt = await publicClient.waitForTransactionReceipt({ hash: BoykaYuriTokenHash });
   console.log("代币合约地址:", BoykaYuriTokenReceipt.contractAddress);
//
const GreenCarbonNFTHash = await deployer.deployContract({
    abi: GreenCarbonNFTArtifact.abi,//获取abi
    bytecode: GreenCarbonNFTArtifact.bytecode,//硬编码
    args: [deployerAddress],//部署者地址,初始所有者地址
  });
  // 等待确认并打印地址
  const GreenCarbonNFTReceipt = await publicClient.waitForTransactionReceipt({ hash: GreenCarbonNFTHash });
  console.log("绿色碳证合约地址:", GreenCarbonNFTReceipt.contractAddress);
  const AlgorithmicEnergyPricingHash = await deployer.deployContract({
    abi: AlgorithmicEnergyPricingArtifact.abi,//获取abi
    bytecode: AlgorithmicEnergyPricingArtifact.bytecode,//硬编码
    args: [deployerAddress,dao.account.address],//部署者地址,初始所有者地址
  });
  // 等待确认并打印地址
  const AlgorithmicEnergyPricingReceipt = await publicClient.waitForTransactionReceipt({ hash: AlgorithmicEnergyPricingHash });
  console.log("算法能源定价合约地址:", AlgorithmicEnergyPricingReceipt.contractAddress);
  const GreenEnergyMarketHash = await deployer.deployContract({
    abi: GreenEnergyMarketArtifact.abi,//获取abi
    bytecode: GreenEnergyMarketArtifact.bytecode,//硬编码
    args: [BoykaYuriTokenReceipt.contractAddress,deployerAddress,dao.account.address],//部署者地址,初始所有者地址
  });
  // 等待确认并打印地址
  const GreenEnergyMarketReceipt = await publicClient.waitForTransactionReceipt({ hash: GreenEnergyMarketHash });
  console.log("绿色能源市场合约地址:", GreenEnergyMarketReceipt.contractAddress);
  const EnergyStakingHash = await deployer.deployContract({
    abi: EnergyStakingArtifact.abi,//获取abi
    bytecode: EnergyStakingArtifact.bytecode,//硬编码
    args: [BoykaYuriTokenReceipt.contractAddress],//部署者地址,初始所有者地址
  });
  // 等待确认并打印地址
  const EnergyStakingReceipt = await publicClient.waitForTransactionReceipt({ hash: EnergyStakingHash });
  console.log("能源质押合约地址:", EnergyStakingReceipt.contractAddress); 
}

main().catch(console.error);

五、技术亮点总结

5.1 模块化设计

  • 各合约职责单一,便于独立升级和维护
  • 通过接口解耦,降低合约间依赖

5.2 渐进式去中心化

  • 初始阶段保留管理员权限便于快速迭代
  • 通过 GOVERNANCE_ROLE 逐步将控制权移交DAO

5.3 经济模型闭环

  • 交易手续费 → 国库 → 质押池 → 质押者收益
  • 激励长期持有者参与协议治理

5.4 现实资产锚定

  • 碳信用NFT锚定真实碳减排数据
  • DePIN设备将物理能源产量上链

    六、潜在优化方向

  1. 预言机去中心化: 集成 Chainlink 或 Band Protocol 替代单一预言机
  2. 动态手续费: 根据市场深度调整手续费率
  3. 跨链桥接: 支持碳信用NFT在其他链上流通
  4. Layer2部署: 降低高频交易的gas成本

    结语

    Energy-Fi Protocol 展示了区块链在能源金融领域的创新应用,通过智能合约实现了能源资产的数字化、交易的透明化以及收益分配的自动化。其DAO治理架构为传统能源市场向去中心化转型提供了可复用的技术范式。

点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
木西
木西
0x5D5C...2dD7
江湖只有他的大名,没有他的介绍。