Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add EIP-5388: Token-Gated HTTP Endpoints #5388

Closed
151 changes: 151 additions & 0 deletions EIPS/eip-5388.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
---
eip: 5388
title: Token-Gated HTTP Endpoints
description: Composable RESTful and Solidity interface to implement token-gated HTTP endpoints using data tokens.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think HTTP and RESTful can be decoupled. If this EIP mandates RESTful API, the title shall reflect it. If it only mandates HTTP, then I think we can drop the RESTful in the description and just keep it about HTTP endpoint?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, I am not sure REST is required/useful?

Copy link
Contributor

@xinbenlv xinbenlv Nov 11, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool!

I kind of like to also have a RESTFul standard, but it can be one level above HTTP, hence that it self could have an separate EIP.

author: Tim Daubenschütz (@TimDaub)
discussions-to: https://ethereum-magicians.org/t/token-gated-https-endpoints/10205
status: Draft
type: Standards Track
category: ERC
lightclient marked this conversation as resolved.
Show resolved Hide resolved
created: 2022-08-01
requires: 712
TimDaub marked this conversation as resolved.
Show resolved Hide resolved
---

## Abstract

This standard introduces composable RESTful HTTP and Solidity interfaces that enable paying to access HTTP endpoints using [EIP-20](./eip-20.md) tokens.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure it is about REST?
Also, why require ERC20... I think it could be more flexible...

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This standard introduces composable HTTP and Solidity interfaces that enable restricting to access HTTP endpoints using smart contracs.


## Motivation

According to RFC 7231, HTTP status code `402 Payment Required` is reserved for future use. But the future is now as Ethereum enables users to verify their identity with a server using public key infrastructure.

The Ethereum community has expressed the need for a composable method of token-gating HTTP endpoints. In this document, we outline a protocol implementable by HTTP servers to accept [EIP-20](./eip-20.md) payments prior to allowing access to an authorized endpoint.

## Specification

The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY" and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.

Upon the user's initial request, an HTTP server implementing token-gating via this EIP responds with a `402 Payment Required` status code:

- Its body must include a valid JSON string that complies with the Solidity Contract ABI Specification for calling contracts.
- It must include a custom header `X-EIP-5388-CONTRACT-ADDRESS` that suggests the contract's address a call must be directed to.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The use of the X- prefix, while very common is actually considered useless (if not harmful..) so I think it would be ok to skip it in favor EIP-5388.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is important to make sure this address is compatible beyond Ethereum mainnet by adding the chain id.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The use of the X- prefix, while very common is actually considered useless (if not harmful..) so I think it would be ok to skip it in favor EIP-5388.

Can u please add a reference that explains why the X- prefix is harmful/useless?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is important to make sure this address is compatible beyond Ethereum mainnet by adding the chain id.

Makes sense, will add it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can u please add a reference that explains why the X- prefix is harmful/useless?

X- headers are for non-standardized headers. So if I have an Application A that needs to return a custom header (for some reason), I should prefix it with X-.

This is a standard. You can (and should) drop the X-.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can u please add a reference that explains why the X- prefix is harmful/useless?

There is a good SO thread there and my good friend Peter wrote an RFC a while back https://www.rfc-editor.org/rfc/rfc6648

https://stackoverflow.com/questions/3561381/custom-http-headers-naming-conventions

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- It must include a custom header `X-EIP-5388-CONTRACT-ADDRESS` that suggests the contract's address a call must be directed to.
- It **MUST** include a custom header `X-EIP-5388-CONTRACT-ADDRESS` that suggests the contract's address a call must be directed to.

- It must include a custom header `X-EIP-5388-ABI-ENCODED-INPUT` that suggests the call signature the user must invoke at `X-EIP-5388-CONTRACT-ADDRESS` to gain access to the endpoint.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- It must include a custom header `X-EIP-5388-ABI-ENCODED-INPUT` that suggests the call signature the user must invoke at `X-EIP-5388-CONTRACT-ADDRESS` to gain access to the endpoint.
- It **MUST** include a custom header `X-EIP-5388-ABI-ENCODED-INPUT` that suggests the call signature the user must invoke at `X-EIP-5388-CONTRACT-ADDRESS` to gain access to the endpoint.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel the spec also lacks a part in solidity interface for what smart contract it will be to respond to a end point request

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure I understand what you mean, would you mind elaborating?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think what @xinbenlv is asking is probably which are these contracts that these endpoints might be dependent on, as suggested in his changes. Is that it?


### Example Response

```
Copy link
Member

@Pandapip1 Pandapip1 Aug 1, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
```
```http

HTTP requests have syntax highlighting available

HTTP/2.0 402 Payment Required
Date: Mon, 01 Aug 2022 13:37:00 GMT
Content-Type: application/json
X-EIP-5388-CONTRACT-ADDRESS: 0x005241438cAF3eaCb05bB6543151f7AF894C5B58
X-EIP-5388-ABI-ENCODED-INPUT: 23b872dd00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007b

"{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"type\":\"function\"}"
```

### Authorization via [EIP-712](./eip-712) Signature

After successfully calling the suggested Ethereum contract with the appropriate inputs, for a user request that containing a validly signed message for endpoint authorization, the server must allow access to the bespoke endpoint.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about said endpoint instead of the bespoke endpoint?


The signature is complaint with [EIP-712](./eip-712.md):

```js
keccak256(abi.encodePacked(
hex"1901",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why?

Copy link
Contributor

@xinbenlv xinbenlv Sep 24, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@TimDaub , The code snippet declares it to be "js" in line 52. Is hex"1901" a legitimate javascript code? if not, I'd suggest updating the code snippet declaration to what language it refers to, or update it to a valid js

DOMAIN_SEPARATOR,
keccak256(abi.encode(
keccak256("Invocation(address contract,string input"),
contract,
keccak256(bytes(input)),
))
))
```

where `DOMAIN_SEPARATOR` must be unique to the chain to prevent replay attacks from other domains, and satisfy the requirements of [EIP-712](./eip-712.md):

```js
DOMAIN_SEPARATOR = keccak256(
abi.encode(
keccak256(
"EIP712Domain(string version,uint256 chainId,string endpoint,string method)"
),
keccak256(bytes(version)),
chainid,
keccak256(bytes(endpoint)),
keccak256(bytes(method))
)
);
```

where `endpoint` must represent the full URL, e.g. `https://ethereum.org/api/v1/cutedoge` and `method` an existing HTTP method.

```js
{
"types": {
"EIP712Domain": [
{
"name": "version",
"type": "string"
},
{
"name": "chainId",
"type": "uint256"
},
{
"name": "endpoint",
"type": "string"
},
{
"name": "method",
"type": "string"
}
],
"Invocation": [
{
"name": "contract",
"type": "address"
},
{
"name": "input",
"type": "string"
}
],
"primaryType": "Invocation",
"domain": {
"version": version,
"chainId": chainid,
"endpoint": endpoint,
"method": method
},
"message": {
"contract": contract,
"input": input
}
}
}
```

The resulting hexadecimal-encoded signature must be included in a user's request to the endpoint as the `Bearer` value of the `Authorization` header. An example:

```http
GET /index.html
Authorization: Bearer 0xabc...
```

Upon validating the signature and cross-checking it with the mandated on-chain interaction, a server must allow access to the appointed endpoint's resource.

## Rationale

There is no rationale related this standard.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
There is no rationale related this standard.
TBD


## Backwards Compatibility

No backward compatibility issues were found.

## Security Considerations

Needs discussion.

## Copyright

Copyright and related rights waived via [CC0](../LICENSE.md).