---
# System prepended metadata

title: Treekipedia - ResearchLogSchema

---

# Treekipedia ResearchLogSchema

https://base-sepolia.easscan.org/schema/view/0x879ed82d38bd26318e55e4803c5699f3191e3e9ca2ffbf75d0cdf16524e4d9d3
```
import  { EAS, SchemaEncoder }  from "@ethereum-attestation-service/eas-sdk";
const easContractAddress = "0x4200000000000000000000000000000000000021";
const schemaUID = "0x879ed82d38bd26318e55e4803c5699f3191e3e9ca2ffbf75d0cdf16524e4d9d3";
const eas = new EAS(easContractAddress);
// Signer must be an ethers-like signer.
await eas.connect(signer);
// Initialize SchemaEncoder with the schema string
const schemaEncoder = new SchemaEncoder("uint256 researchLogID,address triggerWallet,string scientificName,string speciesUID,string[] speciesURL,string llmModel,string ipfsCID,uint16 numberInsights,uint16 numberCitations");
const encodedData = schemaEncoder.encodeData([
	{ name: "researchLogID", value: "0", type: "uint256" }
	{ name: "triggerWallet", value: "0x0000000000000000000000000000000000000000", type: "address" }
	{ name: "scientificName", value: "", type: "string" }
	{ name: "speciesUID", value: "", type: "string" }
	{ name: "speciesURL", value: [], type: "string[]" }
	{ name: "llmModel", value: "", type: "string" }
	{ name: "ipfsCID", value: "", type: "string" }
	{ name: "numberInsights", value: "0", type: "uint16" }
	{ name: "numberCitations", value: "0", type: "uint16" }
]);
const tx = await eas.attest({
	schema: schemaUID,
	data: {
		recipient: "0x0000000000000000000000000000000000000000",
		expirationTime: 0,
		revocable: true, // Be aware that if your schema is not revocable, this MUST be false
		data: encodedData,
	},
});
const newAttestationUID = await tx.wait();
console.log("New attestation UID:", newAttestationUID);

```
# Resolver Contracts
### Attester

This resolver ensures that an attestation is created by a specific attester. It's like a VIP pass, where only a particular entity is allowed to attest.

```
// SPDX-License-Identifier: MIT

pragma solidity 0.8.28;

import { SchemaResolver } from "../SchemaResolver.sol";

import { IEAS, Attestation } from "../../IEAS.sol";

/// @title AttesterResolver
/// @notice A sample schema resolver that checks whether the attestation is from a specific attester.
contract AttesterResolver is SchemaResolver {
    address private immutable _targetAttester;

    constructor(IEAS eas, address targetAttester) SchemaResolver(eas) {
        _targetAttester = targetAttester;
    }

    function onAttest(Attestation calldata attestation, uint256 /*value*/) internal view override returns (bool) {
        return attestation.attester == _targetAttester;
    }

    function onRevoke(Attestation calldata /*attestation*/, uint256 /*value*/) internal pure override returns (bool) {
        return true;
    }
}
```

### Expiration Time

This resolver checks if an attestation's expiration time meets a certain condition. Think of it as a "best before" date for attestations.

```
// SPDX-License-Identifier: MIT

pragma solidity 0.8.28;

import { SchemaResolver } from "../SchemaResolver.sol";

import { IEAS, Attestation } from "../../IEAS.sol";

/// @title ExpirationTimeResolver
/// @notice A sample schema resolver that checks whether the expiration time is later than a specific timestamp.
contract ExpirationTimeResolver is SchemaResolver {
    uint256 private immutable _validAfter;

    constructor(IEAS eas, uint256 validAfter) SchemaResolver(eas) {
        _validAfter = validAfter;
    }

    function onAttest(Attestation calldata attestation, uint256 /*value*/) internal view override returns (bool) {
        return attestation.expirationTime >= _validAfter;
    }

    function onRevoke(Attestation calldata /*attestation*/, uint256 /*value*/) internal pure override returns (bool) {
        return true;
    }
}
```

### Paying Resolver	

This resolver facilitates payments to attesters when they create an attestation. It's a way to incentivize or reward certain attestations.

```
// SPDX-License-Identifier: MIT

pragma solidity 0.8.28;

import { Address } from "@openzeppelin/contracts/utils/Address.sol";

import { SchemaResolver } from "../SchemaResolver.sol";

import { IEAS, Attestation } from "../../IEAS.sol";

/// @title PayingResolver
/// @notice A sample schema resolver that pays attesters (and expects the payment to be returned during revocations).
contract PayingResolver is SchemaResolver {
    using Address for address payable;

    error InvalidValue();

    uint256 private immutable _incentive;

    constructor(IEAS eas, uint256 incentive) SchemaResolver(eas) {
        _incentive = incentive;
    }

    function isPayable() public pure override returns (bool) {
        return true;
    }

    function onAttest(Attestation calldata attestation, uint256 value) internal override returns (bool) {
        if (value > 0) {
            return false;
        }

        payable(attestation.attester).transfer(_incentive);

        return true;
    }

    function onRevoke(Attestation calldata attestation, uint256 value) internal override returns (bool) {
        if (value < _incentive) {
            return false;
        }

        if (value > _incentive) {
            payable(address(attestation.attester)).sendValue(value - _incentive);
        }

        return true;
    }
}

```
### Recipient Resolver

Ensures an attestation is made to a specific recipient. It's like sending a letter, where only the intended recipient should receive it.

```
// SPDX-License-Identifier: MIT

pragma solidity 0.8.28;

import { SchemaResolver } from "../SchemaResolver.sol";

import { IEAS, Attestation } from "../../IEAS.sol";

/// @title RecipientResolver
/// @notice A sample schema resolver that checks whether the attestation is to a specific recipient.
contract RecipientResolver is SchemaResolver {
    address private immutable _targetRecipient;

    constructor(IEAS eas, address targetRecipient) SchemaResolver(eas) {
        _targetRecipient = targetRecipient;
    }

    function onAttest(Attestation calldata attestation, uint256 /*value*/) internal view override returns (bool) {
        return attestation.recipient == _targetRecipient;
    }

    function onRevoke(Attestation calldata /*attestation*/, uint256 /*value*/) internal pure override returns (bool) {
        return true;
    }
}

```

### Token Resolver

Checks if a specific amount of tokens has been approved for an attestation. It integrates token transactions into the attestation process.

```
// SPDX-License-Identifier: MIT

pragma solidity 0.8.28;

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

import { SchemaResolver } from "../SchemaResolver.sol";

import { IEAS, Attestation } from "../../IEAS.sol";

/// @title TokenResolver
/// @notice A sample schema resolver that checks whether a specific amount of tokens was approved to be included in an attestation.
contract TokenResolver is SchemaResolver {
    using SafeERC20 for IERC20;

    error InvalidAllowance();

    IERC20 private immutable _targetToken;
    uint256 private immutable _targetAmount;

    constructor(IEAS eas, IERC20 targetToken, uint256 targetAmount) SchemaResolver(eas) {
        _targetToken = targetToken;
        _targetAmount = targetAmount;
    }

    function onAttest(Attestation calldata attestation, uint256 /*value*/) internal view override returns (bool) {
        if (_targetToken.allowance(attestation.attester, address(this)) < _targetAmount) {
            revert InvalidAllowance();
        }

        return true;
    }

    function onRevoke(Attestation calldata /*attestation*/, uint256 /*value*/) internal pure override returns (bool) {
        return true;
    }
}

```

### Value Resolver

Ensures that an attestation is accompanied by a specific amount of ETH. It's like paying a fee or deposit for the attestation.

```
// SPDX-License-Identifier: MIT

pragma solidity 0.8.28;

import { SchemaResolver } from "../SchemaResolver.sol";

import { IEAS, Attestation } from "../../IEAS.sol";

/// @title ValueResolver
/// @notice A sample schema resolver that checks whether a specific amount of ETH was sent with an attestation.
contract ValueResolver is SchemaResolver {
    uint256 private immutable _targetValue;

    constructor(IEAS eas, uint256 targetValue) SchemaResolver(eas) {
        _targetValue = targetValue;
    }

    function isPayable() public pure override returns (bool) {
        return true;
    }

    function onAttest(Attestation calldata /*attestation*/, uint256 value) internal view override returns (bool) {
        return value == _targetValue;
    }

    function onRevoke(Attestation calldata /*attestation*/, uint256 /*value*/) internal pure override returns (bool) {
        return true;
    }
}
```